Reputation: 81
I'm 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());
Upvotes: 7
Views: 11154
Reputation: 1602
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 };
Upvotes: 1
Reputation: 67627
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.
Upvotes: 3