Reputation: 1964
I ask myself if there is a way to initialize a React Component with props, and automatically make Redux aware of that to update its application state?
I made a Counter example :
import React from 'react';
import {createStore} from "redux"
import {Provider} from "react-redux"
import Counter from "./Counter"
import countReducer from "./ducks.js"
const store = createStore(countReducer)
class App extends React.Component {
render() {
return (
<Provider store={store}>
<div className="App">
<Counter />
</div>
</Provider>
);
}
}
export default App;
Counter.js
import React from 'react';
import {connect} from "react-redux"
import {increment, decrement, reset} from "./ducks"
const Counter = ({count, decrement, increment, reset}) => (
<div>
<h1>Counter</h1>
<button onClick={decrement}>-</button>
<span style={{ margin: "0 10px" }}>{count}</span>
<button onClick={increment}>+</button>
<div>
<button onClick={reset}>Reset</button>
</div>
</div>
);
const mapStateToProps = ({count}) => ({
count
})
const mapDispatchToProps = {
decrement,
increment,
reset
}
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
ducks.js
// action creators
export const increment = () => ({
type: "INC"
})
export const decrement = () => ({
type: "DEC"
})
export const reset = () => ({
type: "RESET"
})
// reducers
export default function countReducer(state = { count: 0 }, action) {
switch (action.type) {
case "INC":
return { count: state.count + 1 }
case "DEC":
return { count: state.count - 1 }
case "RESET":
return state.defaultCount ? {
count: state.defaultCount
} : {
count: 0
}
default:
return state
}
}
It works as expected : we can increment, decrement or reset on value 0.
But what if we want to reset on another value?
class App extends React.Component {
render() {
return (
<Provider store={store}>
<div className="App">
<Counter defaultValue={10}/>
</div>
</Provider>
);
}
}
And another question that comes in my mind is how to manage 2 counters with different counters, while still let redux handle the whole state?
It is quite possible that I want to do something in the wrong way, so I would be grateful even if you have just best practice.
Upvotes: 1
Views: 3405
Reputation: 10179
I ask myself if there is a way to initialize a React Component with props, and automatically make Redux aware of that to update its application state?
My solution for this specification is using the componentDidMount()
lifecycle hook. We might have something like this:
componentDidMount(){
if(this.props.defaultValue){
this.props.initCounter(this.props.defaultValue);
}
}
...
const mapDispatchToProps = dispatch({
...
initCounter: defaultValue => dispatch({type: 'INIT_COUNTER', payload: {defaultValue}})
...
})
We will need to handle this action in the reducer, the implementation is quite similar to the things that you've done.
And another question that comes in my mind is how to manage 2 counters with different counters, while still let redux handle the whole state?
Well then, our state will be an array of counter
object, looks like this:
const reducer = (state = [ { id: 1, value:77 }, { id: 2, value: 88} ], action) => {
switch (action.type):
case 'INCREMENT':
return state.map(c => {
if(action.payload.id === c.id) return {...c, value: c.value + 1};
return c;
});
case 'DECREMENT':
return state.map(c => {
if(action.payload.id === c.id) return {...c, value: c.value - 1};
return c;
})
...
default:
return state;
};
We use the id
to specify the counter which needs to be updated.
Upvotes: 1