HTML 不会在子组件中的道具更改时呈现

时间:2021-05-03 06:57:11

标签: reactjs redux react-redux parent-child render

我正在 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>&nbsp;&nbsp; Activate</button>) : (<button className="btnDeactivate user-disable" id="btnDeactivate" onClick={this.handleDeactivateBtnClick}><i className="fa fa-ban" aria-hidden="true"></i>&nbsp;&nbsp; Deactivate</button>)

0 个答案:

没有答案