我正在 React 中构建后端。在我显示用户列表的地方,单击用户需要显示用户详细信息。所以基本上我创建了一个子组件(user-detail.jsx),它具有用户详细信息 html 并将其包含在父组件(users.jsx)中。想通知子组件是一个功能组件。它允许管理员取消激活用户。因此,当管理员停用用户时,它会调用一个操作并调度成功方法。到目前为止一切正常。
问题是在我的子组件中,未检测到更改。为了验证我已经尝试在“componentWillReceiveProps”中控制消息。但它不会重新渲染 html,因为我需要隐藏“取消激活”按钮并显示“激活”。
我添加了最小代码来解释问题。在每条评论前添加带有序列号 (1, 2,3, 4 ...13) 的评论。
注意:我已经看到过关于堆栈溢出的类似问题。但我找不到任何解决方案。
// 2. this is the first function been called when clicked on each user row
handleVideoDetailClick = (user) => (_event) => {
/*
* this.props.showUserDetail is a mapped action. defined in user.actions.js
*/
this.props.showUserDetail(user);
}
// 3. user.actions.js
function showUserDetail(user) {
return dispatch => {
// 4. userService: it calls a service method which makes an api call and return back the response
userService.getById(user.id)
.then(
result => {
if (result.status === 1) {
// 5. dispatches the success action.
dispatch(success(result.data));
} else {
dispatch(failure(result.data));
dispatch(alertActions.error(result.data));
}
},
error => {
dispatch(failure(error.toString()));
dispatch(alertActions.error(error.toString()));
}
);
};
function success(data) { return { type: userConstants.SHOW_DETAIL, data } }
function failure(error) { return { type: userConstants.FAILURE, error } }
}
// 6. users.reducer.js
export function users(state = {}, action) {
switch (action.type) {
......
......
......
case userConstants.SHOW_DETAIL:
// 7. set the flagDetail button to true and it will show the child component on same page (user.jsx)
return {
...state,
user: action.data.user,
challenges: action.data.challenges,
posts: action.data.posts,
flagDetail: true
};
default:
return state
}
}
// 8. On click of activate/ deactivate this function is been called in user-detail.jsx
handleDeactivateBtnClick() {
const { user } = this.props
this.props.deactivateUser({ id: user.id, isDeactivatedByUser: (user.isDeactivatedByUser ? 0 : 1) });
}
// 9. it calls a service method to activate/ deactivate button
function deactivateUser(reqBody) {
return dispatch => {
dispatch(request());
userService.deactivateUser(reqBody)
.then(
result => {
if (result.status === 1) {
// 10. dispatches the success action.
dispatch(success(result.data));
} else {
dispatch(failure(result.data));
dispatch(alertActions.error(result.data));
}
},
error => {
dispatch(failure(error.toString()));
dispatch(alertActions.error(error.toString()));
}
);
};
function request() { return { type: userConstants.DEACTIVATE_REQUEST } }
function success(data) { return { type: userConstants.DEACTIVATE_SUCCESS, data } }
function failure(error) { return { type: userConstants.DEACTIVATE_FAILURE, error } }
}
// 11. users.reducer.js
export function users(state = {}, action) {
switch (action.type) {
......
......
......
case userConstants.DEACTIVATE_SUCCESS:
let user = state.user
console.log('befere ', user.isDeactivatedByUser)
user.isDeactivatedByUser = user.isDeactivatedByUser ? 0 : 1
// 12. It is working fine, till this point.
console.log('after ', user.isDeactivatedByUser)
return { ...state, loadingDeactivate: false, user: user };
default:
return state
}
}
// 13. This is how the values are being fetched from the props in uder-detail.jsx
function mapState(state) {
const { user, challenges, posts } = state.users;
return { user, challenges, posts };
}
const actionCreators = {
hideUserDetail: userActions.hideUserDetail,
deactivateUser: userActions.deactivateUser,
};
export default connect(mapState, actionCreators)(UserDetail);
<!-- 1. users.jsx (parent component) -->
return (
<tr key={index.toString()}>
<td></td>
<td>{item.id}</td>
<td onClick={this.handleVideoDetailClick(item)}>
<div className='tdImage backgroundProp profile-round' style={{ background: `url("${commonConstants.thumbnailUrl}/${item.profilePic}")` }}>
</div>
</td>
<!-- on click of this, it need to show the detail component -->
<td onClick={this.handleVideoDetailClick(item)}>{item.username}</td>
<td onClick={this.handleVideoDetailClick(item)}>{item.displayName}</td>
<td>{item.email}</td>
<td>{getDeviceTypeById(item.deviceType)}</td>
<td><i className="fa fa-trash" aria-hidden="true"></i>
</td>
</tr>
)
<!-- 7. Here is the activate/ deactivate button child component -->
const btnActivateDeactivate = user && user.isDeactivatedByUser ? (<button className="btnActivate user-disable" id="btnActivate" onClick={this.handleDeactivateBtnClick}><i className="fa fa-user fa-lg"></i><i className="fa fa-check" aria-hidden="true"></i> Activate</button>) : (<button className="btnDeactivate user-disable" id="btnDeactivate" onClick={this.handleDeactivateBtnClick}><i className="fa fa-ban" aria-hidden="true"></i> Deactivate</button>)