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());
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.
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 };