我正在使用http://andrewhfarmer.com/component-communication/#3-callback-functions中的示例来传达从孩子到父母的信息。
我正在尝试用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/react@latest/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/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>
答案 0 :(得分:0)
您无需在案例中保留Star(子)组件的内部状态。只需要保持StarsContainer(父级)的内部状态,并将其作为对子进程的回调传递给它。
在您的情况下,您只在构造函数中将 this.props.rating 分配给 this.state.rating ,这就是每次组件重新启动时的原因渲染,但没有改变。
我根据您的代码做了一个快速摘录。其中大部分已移除<Star />
组件中的 this.state.rating ,其余部分已移除<StarContainer />
的一些道具。
如果您对[{1}}和this.state
更加熟悉,那么您将会发现为什么它被称为 React JS。
this.props
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')
);