简体   繁体   中英

Why am I not getting data from the reducer when I click on a button?

I am using React and Redux to build a simple app. There are four buttons: up, left, down, right. If I click on "up", it moves the item up and when I click "down", the item goes down and so on. However, when I clicked on the buttons, the item does not move at all. Even worse, I did not get any error messages in the console when I clicked on them. Here is my code so far:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, connect } from 'react-redux';
import { createStore, combineReducers } from 'redux';
import './index.css';
import registerServiceWorker from './registerServiceWorker';

const reducers = combineReducers({
    vertical: (state={style: 40}, action) => {
        console.log("Inside the vertial reducer", action.type);
        if (action.type === "UP") {
            //Reassign outside the return statement
            state.style = state.style - 10;
            return state;
        } else if (action.type === "DOWN") {
            state.style = state.style + 10;
            return state;
        } else {
            return state;
        }
    },

    horizontal: (state={style: 40}, action) => {
        console.log("Inside the horizontal reducer", action.type);
        if (action.type === "LEFT") {
            state.style = state.style - 10;
            return state;
        } else if (action.type === "RIGHT") {
            state.style = state.style + 10;
            return state;
        } else {
            return state;
        }
    }
});

const a = state => {
    return {
        vertical: state.vertical.style,
        horizontal: state.horizontal.style
    };
};

const b = dispatcher => {
    return {
        clickUp: () => {
            dispatcher({ type: "UP" })
        },
        clickDown: () => {
            dispatcher({ type: "DOWN" })
        },
        clickLeft: () => {
            dispatcher({ type: "LEFT" })
        },
        clickRight: () => {
            dispatcher({ type: "RIGHT" })
        }
    };
};

const container = connect(a, b);

//This is my component
const C = ({ vertical, horizontal, clickUp, clickDown, clickLeft, clickRight }) => {
        console.log("this is from C", vertical);
        return (
            <div>
                <button onClick={clickUp}>Up</button>
                <button onClick={clickDown}>Down</button>
                <button onClick={clickLeft}>Left</button>
                <button onClick={clickRight}>Right</button>
                <img style={{top:vertical+"px", left:horizontal+"px", position:"absolute", width:"40px", height:"40px"}} src={"https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAglAAAAJDIwYjM0NDEwLTViMTMtNGE2Yi05OGZlLTUwOGE2N2IxMjFlOQ.jpg"} alt="" />
            </div>
        );
};

const App = container(C);

const store = createStore(reducers);

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

I console.log the type in my vertical and horizontal reducers and is giving the correct type when I clicked on the button. When I tried to console.log the vertical in my C component, I am not getting any value when I clicked on a button. It is suppose to log out a number in my console, but is not. So, it seems like my state is not being updated when I clicked on the buttons without giving me any errors in the console. I looked through my code many times and cannot find any thing. May I get advice to how to fix my code and why my code is failing silently?

In your reducer, you are overwriting the previous state instead of creating a new state. Redux won't update the component state as it thinks it is still the same as the previous, and so tries to optimize the rerender process and not do so.

Update your reducers to the following, and your app should work as expected:

const reducers = combineReducers({
    vertical: (state={style: 40}, action) => {
        switch (action.type) {
            case 'UP': {
                return Object.assign({}, state, {
                    style: state.style - 10
                });
            }
            case 'DOWN': {
                return Object.assign({}, state, {
                    style: state.style + 10
                });
            }
            default: {
                return state;
            }
        }
    },

    horizontal: (state={style: 40}, action) => {
        switch (action.type) {
            case 'LEFT': {
                return Object.assign({}, state, {
                    style: state.style - 10
                });
            }
            case 'RIGHT': {
                return Object.assign({}, state, {
                    style: state.style + 10
                });
            }
            default: {
                return state;
            }
        }
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM