1

There are similar questions, but the solutions are not working for me. I cannot see where we instruct React-Redux to put some value on the state. In the following component this part fails (state) => ({ ingredients: state.ingredients }). The reason: state is undefined

import React from 'react';
import { connect } from 'react-redux'

class Ingredients extends React.Component {

    render() {
        return (
            <div>Ingredients</div>
        );
    }
}

export default connect(
    (state) => ({ ingredients: state.ingredients }),  //This fails!
    (dispatch) => ({ 
        createNew: () => dispatch(actions.createNew()), 
        edit: (id) => dispatch(actions.edit(id)) 
    })
)(Ingredients);

The store simply has:

function AppStore(state, action) {
        return { 
            ingredients: { foo: "bar" } 
        };
    }
}

export default AppStore;

There is no way for ingredients to be empty

The Store is binded to the App as:

var appStore = createStore(AppStore);

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

The App component is just a view which contains the component (ingredients) that I really need to have with redux:

class App extends React.Component {
    render() {
        return (
            <div>
                <Header/>
                <Switch>
                    <Route path='/home' component={Home} />
                    <Route path='/recipes' component={Recipes} />
                    <Route path='/ingredients' component={Ingredients} />
                    <Route render={() => <div>Not found!</div>} />
                </Switch>
                <Footer />
            </div>
    );
  }

The Ingredients component is the one at the start of my post. I feel like this Redux magic is missing pieces or it is really counter-intuitive.

How Ingredients component could know the value of "state"? Where is it injected to the component? How Redux would know on which components to inject the state?

I have follow different tutorials and in all of these I can only see createStore is caled, then its assigned to a tag and then "connect" is used to export the component. Is it normal for me too feel very unconfortable with this kind of setup? First I feel bad after accepting React as a "component oriented" way of work to end having all the logic in a single store. Also, I question why the "connect" implementation, when we can have component inheritance (what about extend Redux.ConnectedComponent or something like that?)... Then, all this magical setup... maybe I should try other thing instead of Redux?

EDIT: changed the connect part as:

function mapStateToProps(state) {
    return { ingredients: state.ingredients };
}

function mapDispatchToProps(dispatch) {
    return {
        createNew: () => dispatch(actions.createNew()), 
        edit: (id) => dispatch(actions.edit(id)) 
    };
}

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

With this change (just reordered syntax I think), the state is undefined

EDIT 2: My fault, I was importing a different store to the one shown here If I import the correct one, the state is no longer undefined

1 Answer 1

1

Common practice is to create a separate mapStateToProps function that returns an object, defining a key-value pair for each piece of redux-state you want to make available as a prop in your component.

This will simplify your connect logic significantly.

import React from 'react';
import { connect } from 'react-redux'

class Ingredients extends React.Component {

    render() {
        return (
            <div>{this.props.ingredients.foo}</div>
        );
    }
}

const mapStateToProps = (state) => {
   return {
      ingredients: state.ingredients
   }
}

export default connect(mapStateToProps, { createNew, edit })(Ingredients)

The connect function will hook the store's state object to the function(s) that was passed as the first argument. Similarly you could do the same with your dispatcher functions, using ES6 to pass them in as an object. The dispatch method then gets passed to each of those functions in the 2nd argument.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the help. I changed as suggested. Even changing it, the state is empty (check edit)
Found the problem, upvoted for guidance in better practices
@zameb thanks! What was the problem, I'm really curious :)
I had a really dumb mistake!... I was very distracted in some missing step on the tutorials, but at the end my AppStore was being imported from a wrong path, on where I was preparing another setup. Very ashamed of that, but I guess I will fail less once I get more familiar with the component mindset (and right naming rules)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.