在React-Redux中更改道具后不会再次分派动作

AnA*_*ice 1 reactjs redux react-redux

我有以下React组件:

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);
Run Code Online (Sandbox Code Playgroud)

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';

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

更新资料

通过将以下内容添加到我的SkillPage组件并删除co​​mponentDidMount(),我可以使其“工作”

  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));
    }
  }
Run Code Online (Sandbox Code Playgroud)

这感觉超级hacky。有一个更好的方法吗?

更新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));
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

该解决方案仍然让人感觉超级骇客。

更新3-添加动作创建者

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);
    });
  };
}
Run Code Online (Sandbox Code Playgroud)

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);
    });
  };
}
Run Code Online (Sandbox Code Playgroud)

Shu*_*tri 5

ComponentDidMount在组件安装时,lifeCycle函数仅执行一次。你想要的是componentWillReceiveProps每次道具更改都会执行功能

做这个

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));
    }
}
Run Code Online (Sandbox Code Playgroud)