Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux State in Component

trying to figure out how to pull Redux store state into my component from Redux. I've got mapStateToProps and "connect" wired up. However, when I click my button in "App" component, this.props doesn't have my Redux values in it.

// React and Redux Const
const { Component } = React;
const { render } = ReactDOM;
const { Provider, connect } = ReactRedux;
const {createStore, combineReducers, bindActionCreators } = Redux;



function tweetReducer(state=[],action) {
    if(action.type === 'ADD_TWEET') {
        return state.concat({ id: Date.now(), tweet: action.payload})
    } else {
        return state;
    }
}

const rootReducer = combineReducers ({
    state: (state = {}) => state,
    tweets: tweetReducer
});


class App extends Component{
    buttonClicked() {
        store.dispatch({type: 'ADD_TWEET', payload: 'This is my first 
tweet!'});
        console.log(this.props)
    }
    render() {
        return (
            <div>
                <h5>Hello from App</h5>
                <button onClick={this.buttonClicked.bind(this)}>Button</button>

                <div>-------------------</div>
                <Display />
            </div>
         )
     }
}

class Display extends Component {
    render() {
        return (
            <div>
                <h3>Tweets:</h3>
                {this.props.tweets}
            </div>
        )
    }
}

function mapStateToProps(state) {
    console.log('mapping state to props')

    return {
        tweets: state.tweets
    }
}

let store = createStore(rootReducer)

render (
    <Provider store={store}>
        <App />
    </Provider>
    , document.querySelector('#app')
);
connect(mapStateToProps)(App)

console.log(store.getState());
like image 228
Tony Brackins Avatar asked May 10 '17 19:05

Tony Brackins


2 Answers

Looks like you've got a couple issues there.

First, it helps to understand that connect()(MyComponent) returns a new component that "wraps" around your "real" component. In your example, you're calling connect() after you've rendered <App />, and you aren't actually saving and using the component generated by connect(). What you need is something like:

let store = createStore(rootReducer)

const ConnectedApp = connect(mapStateToProps)(App);

render(
    <Provider store={store}>
        <ConnectedApp />
    </Provider>
, document.querySelector('#app')
);

Second, part of the point of connecting a component is that it shouldn't actually reference the store directly. connect() can take a second parameter, known as mapDispatchToProps. If you don't supply a mapDispatch parameter, it will automatically give your component this.props.dispatch. So, your App component should look like this to start with:

class App extends Component{
    buttonClicked(){
        this.props.dispatch({type: 'ADD_TWEET', payload: 'This is my first tweet!'});
        console.log(this.props)
    }

That should be enough to get the App component receiving data from Redux and dispatching actions.

like image 79
markerikson Avatar answered Sep 30 '22 11:09

markerikson


This is how you should proceed with getting store state in your component.

1) Create reducers folder and create a new file index.js

/* reducers/index.js */

import { combineReducers } from "redux";
import tweetReducer from "./tweetReducer";

const rootReducer = combineReducers({
    tweets: tweetReducer
});

export default rootReducer;

/* reducers/tweetReducer.js */

function tweetReducer(state=[],action) {
    switch(action.type) {
        case 'ADD_TWEET': 
            return state.concat({ id: Date.now(), tweet: action.payload});
        default:
            return state;
    }
}

/* components/App.js */

import React, { Component } from 'react';
import { connect } from 'react-redux';
class App extends Component {
    buttonClicked() {
        this.props.store.dispatch({type: 'ADD_TWEET', payload: 'This is my first 
tweet!'});
        console.log(this.props)
    } 
    render() {
        return (
            <div>
                <h5>Hello from App</h5>
                <button onClick={this.buttonClicked.bind(this)}>Button</button>

                <div>-------------------</div>
                <Display />
            </div>
         )
     }
}
function mapStateToProps(state) {
   console.log('mapping state to props')
   return {
     tweets: state.tweets
   }
}
export default connect(mapStateToProps)(App);

/* components/Display.js */

import React, { Component } from 'react';
  export default class Display extends Component {
     render() {
        return (
            <div>
               <h3>Tweets:</h3>
               {this.props.tweets}
             </div>
        )
     }
  }

/*Main.js */

import React, { Component } from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { store } from "./store";

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

/* store/index.js */

import { createStore, applyMiddleware, compose } from "redux";
import reducers from "../reducers";

const store = createStore(
    reducers,
    composeEnhancers(applyMiddleware())
);

export { store };
like image 43
VivekN Avatar answered Sep 30 '22 12:09

VivekN