React-Redux 中的 props 更改后不会再次调度 Action [英] Action is not dispatched again after the props change in React-Redux
问题描述
我有以下 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屋!