React-Redux和Connect - 为什么我的州没有点击更新?

时间:2017-12-01 04:50:10

标签: reactjs redux react-redux

我是redux的新手,我正在编写一个简单的投票前端,允许用户对他们喜欢的框架(Angular,React,Vue)进行投票。当用户点击他们想要投票的框架时,我打算将商店中的投票增加一个。

我使用combineReducersconnect来促进这一点。但是,每次点击后,状态总是落后一票。一次投票后,状态为0.点击2次后,投票状态为1,等等。

这是我的index.js文件,其中我创建了商店并呈现了应用

//index.js
const combinedReducers = combineReducers({
    "votes": votesReducer,
    "currentPercentages": currentPercentageReducer,
    "pastPercentages": pastPercentageReducer
});

let store = createStore(combinedReducers);

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

这是我的行动

export function voteAction(framework){
    return {
        type: "VOTE",
        payload: framework
    }
}

以下是更新投票状态的相关减速器

const initialVoteState = { angular: 0, react: 0, vue: 0 };

export function votesReducer(state=initialVoteState, action){
    switch(action.type){
        case "VOTE":
            if (action.payload === 'angular'){
                return Object.assign({}, state, {
                    angular: state.angular + 1
                });
            } else if (action.payload === 'react'){
                return Object.assign({}, state, {
                    react: state.react + 1
                });
            } else {
                return Object.assign({}, state, {
                    vue: state.vue + 1
                });
            }
        default:
            return state;
    }

}

最后,这是我拥有的组件,它具有点击处理程序,以便于投票和相应地更新状态。

@connect(state => {
    return {
        votes: {
            angular: state.votes.angular,
            react: state.votes.react,
            vue: state.votes.vue
        },
        currentPercent: {
            angular: state.currentPercentages.angular,
            react: state.currentPercentages.react,
            vue: state.currentPercentages.vue
        },
        pastPercent: {
            angular: state.pastPercentages.angular,
            react: state.pastPercentages.react,
            vue: state.pastPercentages.vue
        }
    }
})
export default class InfoArea extends Component {
    constructor(props){
        super(props);
        this.votedAngular = this.votedAngular.bind(this);
        this.votedReact = this.votedReact.bind(this);
        this.votedVue = this.votedVue.bind(this);
    }

    votedAngular(){
        this.props.dispatch(voteAction('angular'));
        console.log(this.props.votes.angular);
        //the log above will output 0 after the first vote is cast, 1
        after the second vote is cast etc. Why is this the case? Should 
        it not be set to the correct value here since the action has 
        already been dispatched?

    }

    votedReact(){
        this.props.dispatch(voteAction('react'));
    }

    votedVue(){
        this.props.dispatch(voteAction('vue'));
    }

    render(){
        return (
        <div className="info-container">
            <img 
                style={{"marginTop":"25px"}} 
                className="app-img" 
                src={require("../../public/brainbulb.svg")}>
            </img>
            <h2 className="wide">What is your favourite front-end framework in 2017?</h2>
            <h4 style={{"marginTop": "0"}}>Click an image below to vote!</h4>
            <div className="row">
                <div className="images-container">
                    <img
                        onClick={this.votedAngular} 
                        className="framework-logo" 
                        src={require("../../public/angular.png")}>
                    </img>
                    <img 
                        onClick={this.votedReact}
                        className="framework-logo" 
                        src={require("../../public/react.png")}>
                    </img>
                    <img 
                        onClick={this.votedVue}
                        className="framework-logo"
                        src={require("../../public/vue.png")}
                    ></img>
                </div>
            </div>
        </div>
        );
    }
}

另外值得注意的是,当我投票并在浏览器控制台中查看我的商店状态时,这是准确的。然而,我的组成部分仍然落后一票。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

您无法立即更新状态的原因是因为更新商店的操作是异步并且正在编写

votedAngular(){
    this.props.dispatch(voteAction('angular'));
    console.log(this.props.votes.angular);
}

表示您在触发操作后立即尝试检查值。如果您想测试该值,我建议您在componentWillReceiveProps函数

中进行测试
componentWillReceiveProps(nextProps) {
   console.log(nextProps.votes.angular);
}

但是,对于需要测试redux值的此类操作,redux-devtools-extension是理想的工具。