简体   繁体   中英

redux - reducer state is blank

I am trying to replicate something similar to the TodoList example in the the redux docs' basic example . The second reducer receives an array - styleItems = [{... ... }, {... ...}] - and then calls the first function to act on each of the individual objects.

I provide an initialState to the app container via the following, as shown in containers/app.js . However, the state passed to the styleItems reducer seems to be a blank array - each and every time.

However, react renders the UI based on the initial config, and react dev-tools shows the state structure as expected. Is the redux store somehow seeing the same thing as react?

containers/app.js

function starterInfo(state) {
    return {

        // The ID of this particular object
        id: 12345,

        // Various keys and theri css values
        styleItems: [
            {
                pk: 31,
                order: 1,
                label: 'Caption text color',
                css_identifier: '.caption-text',
                css_attribute: 'color',
                css_value: '#FFFFFF'
            },
            {
                pk:23,
                order: 2,
                label: 'Caption link color',
                css_identifier: '.caption-link',
                css_attribute: 'color',
                css_value: '#FEFEFE'
            }
        ],

        // Network state info
        currently_fetching: false,
        currently_posting: false
    }
}

export default connect(starterInfo)(App)

reducers/index.js

// This handles a single styleItem object within the array
function change_css(state = {}, action){
    switch (action.type){
        case actions.CHANGE_CSS:

            if (state.order !== action.order){
                return state
            }

            return {
                ...state,
                css_value
            }

        default:
            return state
    }
}

// This handles the styles array in the global state
function styleItems(state = [], action){
    switch(action.type){       
        case actions.CHANGE_CSS:

            const foobar = state.map(styleItem =>
                change_css(styleItem, action)
                )            

            return foobar

        default:
            return state
    }
}

The short answer is that you're not passing the initial state quite right. The first argument to the connect function for the React Redux bindings is mapStateToProps . The point of this function is to take the state that already exists in your app and map it to props for your component. What you're doing in your starterInfo function is kind of just hard-coding what the state is for your component. Because you're returning a plain object React doesn't really know the difference so it works just fine, but Redux doesn't yet know about your app state.

Instead, what you should do is provide your initial state directly to the reducers, like this:

const intialStyleItemsState = [
    {
        pk: 31,
        order: 1,
        label: 'Caption text color',
        css_identifier: '.caption-text',
        css_attribute: 'color',
        css_value: '#FFFFFF'
    },
    {
        pk:23,
        order: 2,
        label: 'Caption link color',
        css_identifier: '.caption-link',
        css_attribute: 'color',
        css_value: '#FEFEFE'
    }
];

function styleItems(state = intialStyleItemsState, action){ ...

And eventually, because you're splitting your reducers up you'll need to combine them back together again with Redux's combineReducers utility, provide that root reducer to your store and go from there.

You can also pass the initial state using the redux function createstore that take as argument createStore(reducer, [initialState]) http://rackt.org/redux/docs/api/createStore.html

Let's say you have two reducers

change_css(state = {}, action)
function styleItems(state = [], action)

If you use comibneReducer to initialize your state

var reducer = combineReducers({
    css: change_css,
    items: styleItems
})

Now

var store = createStore(reducer)
console.log(store.getState())

Your store will contain { css: {}, items: [] }

Now if you want to initialize the state you can pass the initial state as the second argument of the createStore function.

createStore(reducer, {css:{some properties},items:[{name:"obj1"},{name:"obj2"},{name:"obj3"}]})

Now you store will contain the initial state. {css:{some properties,items:[{name:"obj1"},{name:"obj2"},{name:"obj3"}]}

You can feed this state from server for example and set it as initial state of your application

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