React-Redux 中的 props 更改后不会再次调度 Action [英] Action is not dispatched again after the props change in React-Redux

查看:39
本文介绍了React-Redux 中的 props 更改后不会再次调度 Action的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 React 组件:

从'react'导入React;从 'prop-types' 导入 PropTypes;从'react-redux'导入{connect};从'../../actions/jobTitleSkillsActions'导入{loadJobTitleSkills};从'./SkillList'导入技能列表;class SkillPage 扩展 React.Component {componentDidMount() {如果(this.props.user_positions[0]){this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));}}使成为() {返回 (<div><技能列表技能={this.props.job_title_skills}/>

);}}SkillPage.propTypes = {job_title_skills:PropTypes.array.isRequired,user_positions: PropTypes.array.isRequired,};const mapStateToProps = state =>{返回 {job_title_skills:state.job_title_skills,user_positions: state.user_positions};};导出默认连接(mapStateToProps)(技能页面);

state.user_positions = {} 当组件作为前一个组件呈现时,是提交 state.user_positions 的表单.在 SkillPage 组件呈现之后,state.user_positions 被填充,我在 Redux chrome 扩展中验证了这一点.

问题是这个 SkillPage 组件不会自动重新渲染.我希望组件自动检测 state.user_positions 已更改并重新运行 componentDidMount,然后将调度 loadJobTitleSkills().

我在这里做错了什么?为什么每当 state.user_positions 被修改时我的组件不重新渲染?

userPositionReducer.js:

import * as types from '../actions/actionTypes';常量初始状态 = {}导出默认函数 userPositionReducer(state = initialState, action) {开关(动作.类型){案例类型.CREATE_USERPOSITION_SUCCESS:返回 action.user_position案例类型.LOAD_USERPOSITION_SUCCESS:返回 action.user_positions默认:返回状态;}}

jobTitleSkillsReducer.js:

import * as types from '../actions/actionTypes';常量初始状态 = []导出默认函数 jobTitleSkillsReducer(state = initialState, action) {开关(动作.类型){案例类型.LOAD_JOBTITLESKILLS_SUCCESS:返回 action.job_title_skills默认:返回状态;}}

更新

通过将以下内容添加到我的 SkillPage 组件并删除 componentDidMount(),我能够让它工作"

 componentDidUpdate() {如果(this.props.user_positions[0] && this.props.job_title_skills.length === 0){this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));}}

这感觉超级hacky.有没有更好的方法来做到这一点?

更新 2

使用这个添加:componentWillReceiveProps(nextProps) {如果 (nextProps.user_positions && nextProps.user_positions.length > 0) {如果 (this.props.user_positions[0] !== nextProps.user_positions[0]) {this.props.dispatch(loadJobTitleSkills(nextProps.user_positions[0].job_title_id));}}}

这个解决方案仍然感觉非常hacky.

更新 3 - 添加动作创作者

jobTitleSkillsActions.js

import * as types from './actionTypes';从'../api/JobTitleSkillsApi'导入JobTitleSkillsApi;导出函数 loadJobTitleSkillsSuccess(job_title_skills) {返回{类型:types.LOAD_JOBTITLESKILLS_SUCCESS,job_title_skills};}导出函数 loadJobTitleSkills(job_title_id) {返回函数(调度){返回 JobTitleSkillsApi.getAllJobTitleSkills(job_title_id).then(skills => {dispatch(loadJobTitleSkillsSuccess(skills));}).catch(错误=>{抛出(错误);});};}

UserPositionActions.js

import * as types from './actionTypes';从 '../api/UserPositionsApi' 导入 userPositionsApi;导出函数 createUserPositionSuccess(user_position) {返回 {type: types.CREATE_USERPOSITION_SUCCESS, user_position};}导出函数 loadUserPositionSuccess(user_positions) {返回 {type: types.LOAD_USERPOSITION_SUCCESS, user_positions};}导出函数 loadUserPositions() {//console.log('actions: loadUserPosition')返回函数(调度){返回 userPositionsApi.getAllUserPositions().then(user_positions => {dispatch(loadUserPositionSuccess(user_positions));}).catch(错误=>{抛出(错误);});};}导出函数 createUserPosition(user_position) {//console.log('actions: createUserPosition')返回函数(调度){返回 userPositionsApi.createUserPosition(user_position).then(responseUserPosition => {dispatch(createUserPositionSuccess(responseUserPosition));返回响应用户位置;}).catch(错误=>{抛出(错误);});};}

解决方案

ComponentDidMount lifeCycle 函数只执行一次,在组件挂载时.你想要的是 componentWillReceiveProps 函数,它也会在每次道具更改时执行

这样做

componentDidMount() {如果(this.props.user_positions[0]){this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));}}componentWillReceiveProps(nextProps) {如果 (this.props.user_positions[0] !== nextProps.userPositions[0]) {this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));}}

I have the following React Component:

import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {loadJobTitleSkills} from '../../actions/jobTitleSkillsActions';
import SkillList from './SkillList';

class SkillPage extends React.Component {

  componentDidMount() {
    if (this.props.user_positions[0]) {
      this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));
    }
  }

  render() {
    return (
      <div>
        <SkillList skills={this.props.job_title_skills} />
      </div>
    );
  }
}

SkillPage.propTypes = {
  job_title_skills: PropTypes.array.isRequired,
  user_positions: PropTypes.array.isRequired,
};

const mapStateToProps = state => {
  return {
    job_title_skills: state.job_title_skills,
    user_positions: state.user_positions
  };
};

export default connect(mapStateToProps)(SkillPage);

state.user_positions = {} when the component is rendered as a previous component is a form that submits state.user_positions. Right after the SkillPage component is rendered, state.user_positions is populated, which I validated in the Redux chrome extension.

The problem is this SkillPage component is not automatically re-rendering. I expect the component to automatically detect state.user_positions has changed and rerun componentDidMount, which would then dispatch loadJobTitleSkills().

What am I doing wrong here? Why isn't my component re-rendering whenever state.user_positions is modified?

userPositionReducer.js:

import * as types from '../actions/actionTypes';

const initialState = {}

export default function userPositionReducer(state = initialState, action) {
  switch (action.type) {
    case types.CREATE_USERPOSITION_SUCCESS:
      return action.user_position
    case types.LOAD_USERPOSITION_SUCCESS:
      return action.user_positions
    default:
      return state;
  }
}

jobTitleSkillsReducer.js:

import * as types from '../actions/actionTypes';

const initialState = []

export default function jobTitleSkillsReducer(state = initialState, action) {
  switch (action.type) {
    case types.LOAD_JOBTITLESKILLS_SUCCESS:
     return action.job_title_skills
    default:
      return state;
  }
}

Update

I was able to get it to "work" by adding the following to my SkillPage component and removing componentDidMount()

  componentDidUpdate() {
    if (this.props.user_positions[0] && this.props.job_title_skills.length === 0) {
      this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));
    }
  }

This feels super hacky. Is there a better way to do this?

Update 2

Working with this added:

  componentWillReceiveProps(nextProps) {
    if (nextProps.user_positions && nextProps.user_positions.length > 0) {
      if (this.props.user_positions[0] !== nextProps.user_positions[0]) {
        this.props.dispatch(loadJobTitleSkills(nextProps.user_positions[0].job_title_id));
      }
    }
  }

This solution still feels super hacky.

Update 3 - Adding Action Creators

jobTitleSkillsActions.js

import * as types from './actionTypes';
import JobTitleSkillsApi from '../api/JobTitleSkillsApi';

export function loadJobTitleSkillsSuccess(job_title_skills) {
  return {type: types.LOAD_JOBTITLESKILLS_SUCCESS, job_title_skills};
}

export function loadJobTitleSkills(job_title_id) {
  return function(dispatch) {
    return JobTitleSkillsApi.getAllJobTitleSkills(job_title_id).then(skills => {
      dispatch(loadJobTitleSkillsSuccess(skills));
    }).catch(error => {
      throw(error);
    });
  };
}

UserPositionActions.js

import * as types from './actionTypes';
import userPositionsApi from '../api/UserPositionsApi';

export function createUserPositionSuccess(user_position) {
  return {type: types.CREATE_USERPOSITION_SUCCESS, user_position};
}

export function loadUserPositionSuccess(user_positions) {
  return {type: types.LOAD_USERPOSITION_SUCCESS, user_positions};
}

export function loadUserPositions() {
  // console.log('actions: loadUserPosition')
  return function(dispatch) {
    return userPositionsApi.getAllUserPositions().then(user_positions => {
      dispatch(loadUserPositionSuccess(user_positions));
    }).catch(error => {
      throw(error);
    });
  };
}

export function createUserPosition(user_position) {
  // console.log('actions: createUserPosition')
  return function (dispatch) {
    return userPositionsApi.createUserPosition(user_position).then(responseUserPosition => {
      dispatch(createUserPositionSuccess(responseUserPosition));
      return responseUserPosition;
    }).catch(error => {
      throw(error);
    });
  };
}

解决方案

ComponentDidMount lifeCycle function is only executed once, at the time of component Mount. What you want is the componentWillReceiveProps function which too which gets executed on every prop change

Do this

componentDidMount() {
    if (this.props.user_positions[0] ) {
      this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));
    }
  }
componentWillReceiveProps(nextProps) {

     if (this.props.user_positions[0] !== nextProps.userPositions[0]) {
      this.props.dispatch(loadJobTitleSkills(this.props.user_positions[0].job_title_id));
    }
}

这篇关于React-Redux 中的 props 更改后不会再次调度 Action的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆