2016-12-17 1 views
0

Ich benutzte ein Beispiel von http://andrewhfarmer.com/component-communication/#3-callback-functions, um von einem Kind zu einem Elternteil zu kommunizieren.reactjs update parent dann update Geschwister

Ich versuche ein Sternebewertungssystem mit reactjs zu erstellen. Es aktualisiert den Status der Geschwister nicht, wenn es erneut rendert. Ich habe versucht, this.forceUpdate() und this.render() zu nennen, wenn StarsContainer.onRate() aufgerufen wird, leider behebt das das Problem auch nicht.

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 

Die Debug zeigt deutlich, dass die Mutter StarContainer erneut Rendering, und der Staat für diese Komponente hat die Bewertung von 5. Es zeigt auch, dass die Star Komponenten neu gerendert werden. Die Bewertung wird jedoch nicht für die "Geschwister" aktualisiert.

Habe ich einen Fehler gefunden, oder ist das erwartete Verhalten?

<!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

Vielleicht verwenden Sie nicht 'this.state.rating' und stattdessen nur verwenden' this.props.rating': es wird aktualisiert, wenn die Top-Komponente rerenders –

+0

Sie sind richtig, alles was ich tun musste, war 'Star.render()' in 'const rating = this.props.rating zu ändern; const Wert = this.props.value; ' – the7erm

Antwort

0

Sie müssen den inneren Zustand Ihrer Star (Kind) Komponente in Ihrem Fall nicht behalten. Sie müssen nur den inneren Zustand Ihres StarsContainer (Eltern) behalten und ihn in einem Rückruf als das weitergeben, was Sie an seinen Kindern getan haben.

In Ihrem Fall Sie nur this.props.rating zu this.state.rating im Konstruktor zuweisen, deshalb ist die Komponente jedes Mal neu gerendert wurde, aber nicht ändern.

Ich habe einen kurzen Auszug basierend auf Ihrem Code erstellt. Das meiste ist entfernt this.state.rating in <Star /> Komponente und der Rest davon ist einige Requisiten von <StarContainer /> entfernt.

Wenn Sie mehr vertraut mit this.state und this.props dann bekommen, werden Sie erkennen, warum es heißt Reagieren 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>

Verwandte Themen