2016-12-17 10 views
0

私はhttp://andrewhfarmer.com/component-communication/#3-callback-functionsの例を使って子から親に通信していました。reactjs親を更新して兄弟を更新

私はreactjsで星評価システムを作成しようとしています。それは再レンダリング時に兄弟の状態を更新していません。私はthis.forceUpdate()this.render()を呼び出すときにStarsContainer.onRate()が呼び出されたときに問題を解決しません。

Expected output: 
StarContainer render: 5 <- 
RATING: 5 
Star render: 0 : 5 
Star render: 1 : 5 
Star render: 2 : 5 
Star render: 3 : 5 
Star render: 4 : 5 
Star render: 5 : 5 
Star render: 6 : 5 

Actual output: 
StarContainer render: 5 <- 
RATING: 5 
Star render: 0 : 1 
Star render: 1 : 1 
Star render: 2 : 1 
Star render: 3 : 1 
Star render: 4 : 1 
Star render: 5 : 5 
Star render: 6 : 1 

デバッグは明らか親StarContainer再レンダリングされ、そのコンポーネントの状態は、5の評価またStarコンポーネントが再レンダリングされていることを示しているを有することを示します。ただし、評価は "兄弟"のために更新されていません。

バグが見つかりましたか、これが予期した動作ですか?

<!DOCTYPE html> 
<html> 
    <head> 
    <meta charset="UTF-8" /> 
    <title>Hello World</title> 
    <script src="https://unpkg.com/[email protected]/dist/react.js"></script> 
    <script src="https://unpkg.com/[email protected]/dist/react-dom.js"></script> 
    <script src="https://unpkg.com/[email protected]/babel.min.js"></script> 
    <style> 
     a.star:hover { 
      cursor: pointer; 
      color: red; 
     } 
     a.star { 
      font-size: 2em; 
     } 
    </style> 
    </head> 
    <body> 
    <div id="root"></div> 
    <script type="text/babel"> 

     class Star extends React.Component { 
      constructor(props) { 
       super(props); 
       this.state = { 
        rating: props.rating, 
        value: props.value, 
        onValue: props.onValue, 
        offValue: props.offValue, 
        className: props.className, 
        onRate: props.onRate 
       }; 
      } 

      handleClick(e) { 
       e.preventDefault(); 
       console.log('The link was clicked.'); 
       this.setState({rating: this.state.value}); 
       console.log("this.state.value:",this.state.value); 
       this.props.onRate(this.state.value); 
      } 

      render() { 
       var rating = this.state.rating; 
       var value = this.state.value; 
       console.log("Star render:", value, ":",rating); 

       if (rating >= value) { 
        return(<a className={this.state.className} onClick={(e) => this.handleClick(e)}>{this.state.onValue}</a>); 
       } else { 
        return(<a className={this.state.className} onClick={(e) => this.handleClick(e)}>{this.state.offValue}</a>); 
       } 
      } 
     } 

     Star.propTypes = { 
      onRate: React.PropTypes.func, 
     }; 

     class StarsContainer extends React.Component { 
      constructor(props) { 
       super(props); 

       this.state = { 
        rating: props.rating, 
        className: props.className 
       }; 
      } 
      onRate(newRating) { 
       console.log("StarsContainer onRate:", newRating); 
       this.setState({rating: newRating}); 
       console.log("New Rating:", this.state.rating); 
      } 
      render() { 
       console.log("StarContainer render:", this.state.rating, "<-"); 
       const rating = this.state.rating; 
       console.log("RATING:", rating); 
       return(<span> 
        <Star rating={rating} value="0" onValue="0" offValue=" " className="star" onRate={this.onRate.bind(this)} /> 
        <Star rating={rating} value="1" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
        <Star rating={rating} value="2" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
        <Star rating={rating} value="3" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
        <Star rating={rating} value="4" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
        <Star rating={rating} value="5" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
        <Star rating={rating} value="6" onValue="?" offValue="" className="star" onRate={this.onRate.bind(this)} /> 
       </span>); 
      } 
     } 

     StarsContainer.propTypes = { 
      onRate: React.PropTypes.func, 
     }; 

     ReactDOM.render(
      <StarsContainer rating="1" onValue="+" offValue="-" className="star" />, 
      document.getElementById('root') 
     ); 

    </script> 
    </body> 
</html> 
+1

たぶん 'this.state.rating'を使用していないし、代わりにちょうど' this.props.rating'を使用して:あなたは正しい時にトップコンポーネントの再レンダリング –

+0

それが更新されます、私がしなければならなかったのは、 'Star.render()'を 'const rating = this.props.rating;に変更することでした。 const value = this.props.value; ' – the7erm

答えて

0

スター(子)コンポーネントの内部状態を保持する必要はありません。あなたのStarsContainer(親)の内部状態を保持し、その子に行ったことと同様にコールバックで渡すだけでよい。あなたのケースでは

、あなただけのコンストラクタでthis.props.ratingにthis.state.ratingを割り当てるたびにコンポーネントが再レンダリングされていますが、変更しなかった理由、それはです。

あなたのコードに基づいて簡単なスニペットを作成しました。そのほとんどは削除されてthis.state.rating<Star />のコンポーネントと残りの部分が削除されます<StarContainer />のいくつかの小道具。

this.statethis.propsをよく知っていれば、なぜそれがリアクション JSと呼ばれるのか分かります。

 class Star extends React.Component { 
 
      constructor(props) { 
 
       super(props); 
 
       this.state = { 
 
        onValue: props.onValue, 
 
        offValue: props.offValue, 
 
        className: props.className, 
 
        onRate: props.onRate 
 
       }; 
 
      } 
 

 
      handleClick(e) { 
 
       e.preventDefault(); 
 
       console.log('The link was clicked.'); 
 
       console.log("this.state.value:",this.props.value); 
 
       this.props.onRate(this.props.value); 
 
      } 
 

 
      render() { 
 
       var rating = this.props.rating; 
 
       var value = this.props.value; 
 
       console.log("Star render:", value, ":",rating); 
 

 
       if (rating >= value) { 
 
        return(<a className={this.state.className} onClick={(e) => this.handleClick(e)}>{this.state.onValue}</a>); 
 
       } else { 
 
        return(<a className={this.state.className} onClick={(e) => this.handleClick(e)}>{this.state.offValue}</a>); 
 
       } 
 
      } 
 
     } 
 

 
     Star.propTypes = { 
 
      onRate: React.PropTypes.func, 
 
     }; 
 

 
     class StarsContainer extends React.Component { 
 
      constructor(props) { 
 
       super(props); 
 

 
       this.state = { 
 
        rating: 0, 
 
        className: props.className 
 
       }; 
 
      } 
 
      onRate(newRating) { 
 
       console.log("StarsContainer onRate:", newRating); 
 
       this.setState({rating: newRating}); 
 
       console.log("New Rating:", this.state.rating); 
 
      } 
 
      render() { 
 
       console.log("StarContainer render:", this.state.rating, "<-"); 
 
       const rating = this.state.rating; 
 
       console.log("RATING:", rating); 
 
       return(<span> 
 
        <Star rating={rating} value="0" onValue="0" offValue=" " className="star" onRate={this.onRate.bind(this)} /> 
 
        <Star rating={rating} value="1" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
 
        <Star rating={rating} value="2" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
 
        <Star rating={rating} value="3" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
 
        <Star rating={rating} value="4" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
 
        <Star rating={rating} value="5" onValue="+" offValue="-" className="star" onRate={this.onRate.bind(this)} /> 
 
        <Star rating={rating} value="6" onValue="?" offValue="" className="star" onRate={this.onRate.bind(this)} /> 
 
       </span>); 
 
      } 
 
     } 
 

 
     StarsContainer.propTypes = { 
 
      onRate: React.PropTypes.func, 
 
     }; 
 

 
     ReactDOM.render(
 
      <StarsContainer onValue="+" offValue="-" className="star" />, 
 
      document.getElementById('root') 
 
     );
<html> 
 
    <head> 
 
    <meta charset="UTF-8" /> 
 
    <title>Hello World</title> 
 
    <script src="https://unpkg.com/[email protected]/dist/react.js"></script> 
 
    <script src="https://unpkg.com/[email protected]/dist/react-dom.js"></script> 
 
    <script src="https://unpkg.com/[email protected]/babel.min.js"></script> 
 
    <style> 
 
     a.star:hover { 
 
      cursor: pointer; 
 
      color: red; 
 
     } 
 
     a.star { 
 
      font-size: 2em; 
 
     } 
 
    </style> 
 
    </head> 
 
    <body> 
 
    <div id="root"></div> 
 
    </body> 
 
</html>

関連する問題