React props不会更新调度操作

时间:2016-10-28 09:09:57

标签: javascript reactjs redux react-redux

我几天来一直在寻找答案而且它真的很令人沮丧。我刚刚开始学习React,并遇到了这个麻烦:   我有一个项目reducer就是这个(projectReducers.js):

const projectReducer = (state = {
        fetching: false,
        fetched: false,
        item: {},
        items: []
    }, action) => 
{
switch(action.type){

    case 'GET_PROJECT_START':{
        state = { ...state, fetching: true};
    }
        break;
    case 'GET_PROJECT_RECEIVED':{
        state = {...state,  fetching: false, fetched: true, item: action.payload };
    }
        break;
    case 'GET_PROJECT_ERROR':{
        state = { ...state, fetching: false, error: action.payload };
    }


    case 'GET_PROJECTS_START':{
        state = { ...state, fetching: true};
    }
        break;
    case 'GET_PROJECTS_RECEIVED':{
        state = {...state,  fetching: false, fetched: true, items: action.payload };
    }
        break;
    case 'GET_PROJECTS_ERROR':{
        state = { ...state, fetching: false, error: action.payload };
    }
}
return state
};

export default projectReducer;

P.S。我知道GET_PROJECT_START和GET_PROJECTS_START也是这样做的,我现在把它们分开是为了我自己的清晰度。

动作(projectActions.js):

export function createProject(number){
    return {
        type: 'CREATE_PROJECT',
        payload: number
        }
};

export function getProjectStart(){
    return {
        type: 'GET_PROJECT_START'
    }
};

export function getProjectReceived(project){
    return {
        type: 'GET_PROJECT_RECEIVED',
        payload: project
    }
};

export function getProjectError(err){
    return {
        type: 'GET_PROJECT_ERROR',
        payload: err
    }
};

export function getProjectsStart(){
    return {
        type: 'GET_PROJECTS_START'
    }
};

export function getProjectsReceived(projects){
    return {
        type: 'GET_PROJECTS_RECEIVED',
        payload: projects
    }
};

export function getProjectsError(err){
    return {
        type: 'GET_PROJECTS_ERROR',
        payload: err
    }
};

我将reducers与combineReducers结合使用并创建store(store.js):

import {createStore, combineReducers, applyMiddleware} from 'redux';
import logger from 'redux-logger';

import mathReducer from './reducers/mathReducer'; //not relevant
import userReducer from './reducers/userReducer'; //not relevant
import projectReducer from './reducers/projectReducer';

export default createStore(
    combineReducers({mathReducer, userReducer, projectReducer}),
    {},
    applyMiddleware(logger()) <- log changes
);

将来自react-redux的Provider中的根组件包装起来以绑定商店(Index.js)

render(
    <Provider store={store}>
        <App/>
    </Provider>,
    window.document.getElementById('app')
);

使用connect(App.js)将商店绑定到root app props

class App extends React.Component {

    render() {
        return (
            <Router history={browserHistory}>
                <Route path="/login" component={Login}/>
                <Route path="/" component={Dashboard}>
                    <IndexRoute component={Home}/>
                    <Route path="/home" component={Home}/>
                    <Route path="/blank" project={this.props.project} projectActions={this.props.projectActions} component={Projects}/>
                </Route>
            </Router>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        math: state.mathReducer,
        user: state.userReducer,
        project: state.projectReducer
    };
};

const mapDispatchToProps = (dispatch) => {
    return {
        projectActions :{
            getProjectStart: () => {dispatch(getProjectStart())},
            getProjectReceived: (project) => {dispatch(getProjectReceived(project))},
            getProjectError: (err) => {dispatch(getProjectError(err))},
            getProjectsStart: () => {dispatch(getProjectsStart())},
            getProjectsReceived: (project) => {dispatch(getProjectsReceived(project))},
            getProjectsError: (err) => {dispatch(getProjectsError(err))}
        }
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(App);

然后使用从服务器获取的(Projects.js)中传递的道具:

export default class Projects extends React.Component {

    fetchProjects() {
        let projectActions = this.props.route.projectActions;
        projectActions.getProjectsStart();
        console.log(this.props.route.project);

        fetch('http://localhost:3000/projects/').then((response)=> {
            setTimeout(() => {
                projectActions.getProjectsReceived(response.json());
                console.log(this.props.route.project);
            }, 5000);

        })
    }

    componentWillMount() {
        this.fetchProjects();
    }

    render() {
        return (
            <div>
                <div className="row">
                    <h1>Projects</h1>
                    {this.props.route.project.fetching ? <span> receiving data</span> : <span> Not receiving data </span>}
                </div>
            </div>
        )
    }
}

这里有趣的事情发生在this.props.route.project永远不会更新span-&gt;不接收数据永远不会改变,即使我添加了一个巨大的5s延迟。然而,显示(prev state | action | next状态)的redux-logger显示所有正确的更改。我的绑定出错的地方?

1 个答案:

答案 0 :(得分:0)

componentWillMount在渲染之前运行,如果你想让一个动作影响你的渲染,你应该使用componentDidMount。