Reputation: 2048
I have an app where combineReducers is used as it is prescribed by react-redux
pack. So in my connected component I have a function
function mapStateToProps(state){
return {
listedComments: // a prop name
state.allcomments // a reducer name
}
}
...where allcomments
is the name of one of the reducers. But I have only one reducer for now, so I wonder is it possible to not use combineReducers at all, but keep using that functions?
UPDATE
I have an app where combineReducers is used as it is prescribed by react-redux
pack. So in my connected component I have a function
function mapStateToProps(state){
return {
listedComments: // a prop name
state.allcomments // a reducer name
}
}
...where allcomments
is the name of one of the reducers. But I have only one reducer for now, so I wonder is it possible to not use combineReducers at all, but keep using that functions?
UPDATE
Sorry, it seems that I have provided not enough details. So, the app is structured like this:
actions
default.js
components
App.js
Buttons.js
reducers
default.js
index.js
It works perfectly with combineReducers, but doesn't without it as something is wrong in the code. Here the parts of the app (which is of course, very primitive) being responsible for the problem:
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import defaultReducer from './reducers/default'
import App from './components/App'
ReactDOM.render(
<Provider store={createStore(defaultReducer, {})}>
<App />
</Provider>,
document.getElementById('root')
);
const defaultReducer = (state =0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
export default defaultReducer;
import React from 'react'
import Buttons from './Buttons'
import { connect } from 'react-redux'
class App extends React.Component {
renderCount(){
return this.props.count;
}
render() {
return (
<React.Fragment>
<div>Hello again!</div>
<hr />
Look here: {this.renderCount()}
<hr />
<Buttons />
</React.Fragment>
)
}
}
function mapStateToProps(store) {
return { count: store.defaultReducer }
}
export default connect(mapStateToProps)(App)
I supposed that mapStateToProps can use store, which, supposedly, is shipped by Provider. but it is an empty object.
Upvotes: 1
Views: 1502
Reputation: 4344
It seems like you're stuck with the shape of your state, honestly the best place to start if by actually looking at that it is (e.g. by adding a console.log(state)
to your mapStateToProps
).
If we go back to basics, a reducer is just a function that takes a state and an action and returns a new state. This applies to all reducers, including your defaultReducer
. Whatever that reducer returns is the state of your store. So in your case:
const defaultReducer = (state = 0, action) => {
switch (action.type) {
...
default: return state
}
}
// you don't need the second parameter for createStore as you're not
// pre-populating the store with a specific non-default state. You
// can just rely on the default argument from your reducer to set the
// initial state.
const store = createStore(defaultReducer)
console.log(store.getState())
// outputs: 0
The state is just the single integer that your reducer returns. And your mapStateToProps
would end up being:
const mapStateToProps = (state) => {
return { count: state }
}
(As a side note, mapStateToProps
is passed the state, not the store itself, so we usually name its argument state
.)
Upvotes: 0
Reputation: 5224
You are misunderstanding what mapStatetoProps()
is all about. This response may seem redundant, but its function is to map the App's state to the props in your component/container, just like the name implies. Reducers will update the App's state, and by using mapStatetoProps()
, your components/containers can reflect this in their props. Am I misunderstanding your question?
EDIT:
You don't need to use combineReducers()
because you can have one reducer with everything in it as Zaid commented. Either way, you're not going to specifically reference a reducer in mapStatetoProps()
and you do need to do use this function. Something like this:
function mapStateToProps(state){
return {
listedComments: state.listedComments,
allcomments: state.allComments
}
}
State will be pushed into mapStateToProps()
with Redux's
help. Make sure you're using Redux's
connect to hook your components into Redux
:
import { connect } from "react-redux";
EDIT 2: Your reducer isn't right. You're trying to increment state (the store) which is not possible. You need to have a property in state that you increment, like 'counter'. And remember that you should not mutate state. So, something like this:
const initialState = {
counter: 0
};
const defaultReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return [
...state,
{
counter: state.counter + 1
}
];
case 'DECREMENT':
return [
...state,
{
counter: state.counter - 1
}
];
default:
return state;
}
}
export default defaultReducer;
Also, the createStore() looks a bit odd to me. I think it should look more like this (I may be totally wrong about this);
<Provider store={createStore(defaultReducer}>
Upvotes: 1