Reputation: 2060
So, I'm building a small app to learn some redux/react. The app includes a form that is built as a component with a Save button (and some more irrelevant code), and a child component that includes the form fields.
My intention is to update the app state, handled by redux, by dispatching a "SAVE" action (from the parent component) when clicking the "save" button, sending as payload the data from the fields inside the child component.
Is there a react-friendly way to do it?
Upvotes: 0
Views: 841
Reputation: 15530
If some portion of global state is shared between several components wrapped by common (parent) component, you may try to:
SAVE
action to update global stateYou may find the quick demo below:
//dependencies
const { useState } = React,
{ render } = ReactDOM,
{ createStore } = Redux,
{ useDispatch, useSelector, Provider } = ReactRedux
//action, initial state, reducer, store
const SAVE_FEEDBACK = 'SAVE_FEEDBACK',
initialState = {scores:[]},
appReducer = (state=initialState, action) => {
switch(action.type){
case SAVE_FEEDBACK : {
const {scores} = state,
{score} = action
return {...state, scores:[...scores, score]}
}
default: return state
}
},
store = createStore(appReducer)
//form component
const ScoreForm = ({onScoreInput, onNameInput}) => (
<form>
<select onChange={e => onScoreInput(e.target.value)}>
<option value="" selected></option>
<option value="awfull">awfull</option>
<option value="awsome">awsome</option>
</select>
<input onKeyUp={e => onNameInput(e.target.value)} />
</form>
)
//parent component
const MovieScore = () => {
const [userScore, setScore] = useState(''),
[userName, setName] = useState(''),
dispatch = useDispatch(),
userScores = useSelector(({scores}) => scores),
handleScoreInput = score => setScore(score),
handleNameInput = name => setName(name),
onSave = () => dispatch({type: SAVE_FEEDBACK, score: {userName, userScore}})
return (
<div>
<img
src="https://upload.wikimedia.org/wikipedia/uk/a/a4/Knockin.jpg"
style={{maxHeight:200}}
/>
<ScoreForm
onScoreInput={handleScoreInput}
onNameInput={handleNameInput}
/>
<button onClick={onSave}>Save</button>
<div>
{userScores.map(({userScore,userName}) => <div>{userName} thinks, this movie is {userScore}</div>)}
</div>
</div>
)
}
//wrap into Provider component
render (
<Provider {...{store}}>
<MovieScore />
</Provider>,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.3/react-redux.min.js"></script><div id="root"></div>
Upvotes: 1