我有一个名为UsersTable
的父组件(它是其他组件的子组件,并且users
和roles
作为其道具)。 getRoles()
函数使用ajax请求获取用户的所有角色。结果返回render()
并存储在allroles
变量中。问题是因为Ajax是异步的,我并不总是在allroles
变量中得到我需要的值。它有时为空或为所有用户返回相同的值。我想我应该根据描述以某种方式使用componentDidMount和componentWillReceiveProps。但我无法理解。另外,我认为allroles
应该是一个状态,但这样做会使代码处于无限循环中,浏览器会一直调用ajax请求!
这是父组件代码:
export const UsersTable = React.createClass({
getRoles(){
var oneRole = "";
this.props.users.forEach(function(user){
server.getUserRoles(user.id,
(results) => {
this.oneRole =results['hits']['hits']
notifications.success("Get was successful ");
},
() => {
notifications.danger("get failed ");
});
}.bind(this));
return this.oneRole;
},
render() {
var rows = [];
var allroles = this.getRoles()
this.props.users.map(function(user) {
rows.push( <UserRow userID={user.id}
userEmail={user.email}
userRoles={allroles}
roles={this.props.roles} />);
}.bind(this));
return (
<table className="table">
<thead>
<tr>
<th>Email Address</th>
<th>Role</th>
<th>Edit</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}
});
这是子组件代码:
export const UserRow = React.createClass({
var showRoles = this.props.userRoles.map((role) => <div> {role.description || ''}</div>);
render(){
return (
<tr>
<td>{this.props.userEmail}</td>
<td>{showRoles}</td>
</tr>
);
}
});
答案 0 :(得分:0)
你说你应该使用生命周期方法是正确的。
作为一般规则,如果您只需要在开头填充一次数据,请使用componentDidMount
。
如果必须收集更多数据(基于道具更改),请使用componentWillReceiveProps
。
作为旁注,对于您的特定示例,您似乎通过循环多次调用后端。从问题中无法分辨,但如果您使用的是诺言库,您可以将所有这些承诺推送到数组中,然后执行Promise.all().then(/* update state */)
答案 1 :(得分:0)
首先,要将其置于一个状态而不使其成为无限循环,您需要一个构造函数方法,您可以在其中调用super()方法,然后您就可以定义状态。所以你需要这样的东西:
constructor() {
super();
this.state = {
allroles: null
}
}
之后,正如您正确指出的那样,您需要生命周期钩子:componentDidMount()
,
您需要第一个填充您的州。所以要调用它,应该看起来像这样:
componentDidMount() {
this.setState({allroles: this.getRoles()})
}
现在,如果您需要获取新更新,您必须知道此更新是否将作为用户的交互结果(例如,他们在表上添加新条目)或基于时间的更新(例如,使用调用{的间隔)来触发每隔一定时间{1}}。无论哪种方式,您都需要再次使用this.getRole()
。
在这种情况下,您不需要this.setState({allroles: this.getRoles()})
,因为此组件在不接收道具的情况下管理自己的状态。如果您已经收到角色作为道具,则需要componentWillReceiveProps()
最后,回答为什么你有一个无限循环是因为componentWillReceiveProps()
触发了组件的重新渲染。这意味着,如果您在this.setState()
方法中致电this.setState()
,则
这就是为什么你不能在你的render()
方法中直接调用this.setState()
而是在事件或某些生命周期钩子上调用它(在渲染发生之前被调用的那些或被认为是成为INITIAL渲染)