I'm trying to update params then using those values in a search function. In my code, the dispatch does not update the state.params as intended.
import React, { useReducer } from 'react'
const SearchForm = () => {
let searchParams = {}
const initialState = {
params: {}
}
const reducer = (state, action) => {
switch (action.type) {
case 'UPDATE':
return {
...state,
params: action.searchParams
}
default:
return state
}
}
const [state, dispatch] = useReducer(reducer, initialState)
const handleChange = (e) => {
const { name, value } = e.target
searchParams = { ...searchParams, [name]: value }
}
const handleClick = () => {
searchParams = { ...searchParams }
console.log('SearchParams: ', searchParams)
dispatch({ type: 'UPDATE', searchParams })
// state.params returns nothing here
console.log('Handle Click Dispatch: ', state.params)
}
return (
<div>
<select name="gender" onChange={handleChange}>
<option value="">-- Choose --</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select><br />
<select name="ethnicity" onChange={handleChange}>
<option value="">-- Choose --</option>
<option value="African-American">African American</option>
<option value="Caucasian">Caucasian</option>
<option value="Hispanic">Hispanic</option>
</select><br />
<button type="submit" onClick={handleClick}>Submit</button>
</div>
)
}
export default SearchForm
handleChange should update the searchParams variable then dispatch in the onClick method making it available for the rest of the app. What am I missing?
As stated in the comment; you cannot get the state after a dispatch because dispatch is asynchronous and doesn't return anything.
You could add a useEffect and do something there when state.params changed, set initial value of state.params to NONE so you can skip the first time state.params changed:
import React, {
useReducer,
useState,
useEffect,
useCallback,
} from 'react';
const NONE = {};
const initialState = {
params: NONE,
};
const reducer = (state, action) => {
switch (action.type) {
case 'UPDATE':
console.log('in reducer:', action.params);
return {
...state,
params: action.params,
};
default:
return state;
}
};
const SearchForm = () => {
const [searchParams, setSearchParams] = useState({});
const [state, dispatch] = useReducer(
reducer,
initialState
);
const handleChange = useCallback(
e => {
const { name, value } = e.target;
setSearchParams({ ...searchParams, [name]: value });
},
[searchParams]
);
const handleClick = useCallback(() => {
console.log('SearchParams: ', searchParams);
dispatch({ type: 'UPDATE', params: searchParams });
}, [searchParams]);
const { params: stateParams } = state;
useEffect(() => {
if (stateParams !== NONE) {
console.log('params in state changed: ', stateParams);
}
}, [stateParams]);
return (
<div>
<select name="gender" onChange={handleChange}>
<option value="">-- Choose --</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
<br />
<select name="ethnicity" onChange={handleChange}>
<option value="">-- Choose --</option>
<option value="African-American">
African American
</option>
<option value="Caucasian">Caucasian</option>
<option value="Hispanic">Hispanic</option>
</select>
<br />
<button type="submit" onClick={handleClick}>
Submit
</button>
</div>
);
};
export default SearchForm;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With