2017-08-21 11 views
1

私は説明できないReactコンポーネントで本当に奇妙な動作に直面しました。子コンポーネントは関数のプロパティなしでは更新されません

これが私のアプリのバージョンです縮小さ:

class Child extends React.Component { 
 
    componentDidUpdate(prev) { 
 
    if (!prev.isActive && this.props.isActive) { 
 
     console.log('activated', this.props.title); 
 
    } 
 
    } 
 

 
    render() { 
 
    return (
 
     <span 
 
     className={this.props.isActive ? 'child active' : 'child'} 
 
     onClick={this.props.onClick} 
 
     > 
 
     {this.props.title} 
 
     </span> 
 
    ); 
 
    } 
 
} 
 

 
const Child1 = reactRedux.connect((state, props) => ({ 
 
    isActive={props.isActive('Child1')} 
 
    onClick={() => props.activate('Child1')} 
 
    title="Child1" 
 
}))(Child); 
 

 
const Child2 = reactRedux.connect((state, props) => ({ 
 
    isActive={props.isActive('Child2')} 
 
    onClick={() => props.activate('Child2')} 
 
    title="Child2" 
 
}))(Child); 
 

 
class Root extends React.Component { 
 
    state = { active: null }; 
 

 
    activate = (active) => { 
 
    if (!this.isActive(active)) { 
 
     this.setState({ active }); 
 
    } 
 
    }; 
 

 
    isActive = active => this.state.active === active; 
 

 
    renderChild = (ChildComponent, i) => (
 
    <ChildComponent 
 
     activate={this.activate} 
 
     isActive={this.isActive} 
 
     key={i} 
 
    /> 
 
); 
 

 
    render() { 
 
    const children = [Child1, Child2]; 
 

 
    return (
 
     <reactRedux.Provider store={this.props.store}> 
 
     <div>{children.map(this.renderChild)}</div> 
 
     </reactRedux.Provider> 
 
    ); 
 
    } 
 
} 
 

 
const reducer = (state, action) => ({}); 
 
const store = redux.createStore(reducer); 
 
    
 
ReactDOM.render(<Root store={store} />, document.getElementById('root'));
<div id="root"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

[OK]を、問題は、子コンポーネントのcomponentDidUpdateが呼ばれなかったこと、です。しかし、私がすべての子プロパティに関数を含むプロパティを渡すと、それは魅力のように機能します。

renderChild = (ChildComponent, i) => (
    <ChildComponent 
    activate={this.activate} 
    isActive={this.isActive} 
    key={i} 
    asfafasg={() => {}} 
    /> 
); 

その行動はから来たんどこを知っている誰もがありますか?それは本当に奇妙です。私はすでにwebpack builderなどを再起動して、これが奇妙なキャッシングの問題ではないことを確認しました。

スパンをクリックすると、ルートコンポーネントの状態は正しく更新されますが、子のcomponentDidUpdateメソッドは正しく更新されません。

私はリアクタンスレスキューの接続機能を使わずにテストしています。だから、それはconnect関数の問題だと思われます。

+0

意味したのですか?ところで、あなたはどこで 'activate'と呼んでいますか? –

+0

申し訳ありませんが、この例ではactivateメソッドを呼び出すのを忘れていました。私の質問を更新しました。スパンをクリックすると、ルートコンポーネントの状態は正しく更新されますが、子のcomponentDidUpdateメソッドは更新されません。 –

+0

実際のコードは再現されていますが、このエラーが発生してここでは縮小された例だけです。 :/ –

答えて

0

OK(あなたがclassconstructorを使用していないという事実のそばに)、私は解決策を発見した(と理由)に正常に見えます。この動作は、パフォーマンスの最適化react-reduxから発生します。私はそれを最適化するためにreact-reduxに言わなければならないし、それは動作します。この質問は一種の関連である:あなたの代わりに `` componentDidUpdate`のcomponentDidMount`を呼び出すために

React componentDidUpdate method won't fire on inherited props change if connected to a store that didn't change

1

あなたのコードは、私

class Child extends React.Component { 
 
    componentDidUpdate(prev) { 
 
    if (!prev.isActive && this.props.isActive) { 
 
     console.log('activated', this.props.children); 
 
    } 
 
    } 
 

 
    render() { 
 
    return (
 
     <span 
 
     className={this.props.isActive ? 'child active' : 'child'} 
 
     onClick={this.props.onClick} 
 
     > 
 
     {this.props.children} 
 
     </span> 
 
    ); 
 
    } 
 
} 
 

 
const Child1 = props => (
 
    <Child 
 
    isActive={props.isActive('Child1')} 
 
    onClick={() => props.activate('Child1')} 
 
    > 
 
    Child1 
 
    </Child> 
 
); 
 

 
const Child2 = props => (
 
    <Child 
 
    isActive={props.isActive('Child2')} 
 
    onClick={() => props.activate('Child2')} 
 
    > 
 
    Child2 
 
    </Child> 
 
); 
 

 
class Root extends React.Component { 
 
    state = { active: null }; 
 

 
    activate = (active) => { 
 
    if (!this.isActive(active)) { 
 
     this.setState({ active }); 
 
    } 
 
    }; 
 

 
    isActive = active => this.state.active === active; 
 

 
    renderChild = (ChildComponent, i) => (
 
    <ChildComponent 
 
     activate={this.activate} 
 
     isActive={this.isActive} 
 
     key={i} 
 
    /> 
 
); 
 

 
    render() { 
 
    const children = [Child1, Child2]; 
 

 
    return <div>{children.map(this.renderChild)}</div>; 
 
    } 
 
} 
 
ReactDOM.render(<Root />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 

 
<div id="root"></div>

+2

彼はプロトタイプチェーンにもコンストラクタを必要としません。また、 '=>' –

+0

を介してインスタンスにメソッドをバインドするだけでなく、 'state = {}'を直接行うことを可能にする静的プロパティとメンバプロパティbabel transformを使用します。彼はバーベル変換でその構文を行うことができることを知っている、これは私が彼のコードを手つかずのままにした理由です。私はそれをコンストラクタに初期コードを配置する反応のパターンと見なされているが、それを言及した。 –

+0

これは、_OOP_のパターンとみなされ、上書き/拡張したい_method_に[x] _code_を配置します。彼はミドルウェアが彼のためにそれをするが、彼は何も持っていない。コンストラクタのコードに関しては、 'shouldComponentUpdate(... args){return(localLogic)&& super.shouldComponentUpdate(... args)}'のようなものを実行することもできます。 –

関連する問題