Reputation: 619
I have a react component that has 3 input fields and a button.
The component is connected to a redux store.
There is an action creator that makes a web API call to get the user's locational information and changes the state in the redux store.
The onClick
event of the button in the form has a handleOnClick
handler, which calls the action to update the store's state, and then it calls setFormData
to update the values in the input fields to change the input fields' values.
import React, {useState} from 'react';
import {connect} from 'react-redux';
import {setLocation} from "../actions/location.js";
const LocationForm = ({location, setLocation}) => {
const [formData, setFormData] = useState({
city:"",
state:"",
country:""
})
const handleOnChange = (e) => {
setFormData({...formData, [e.target.name]:e.target.value})
}
const handleOnClick = () => {
setLocation();
console.log(location) //!! output: {city:"", state:"", country:""}
const {city, state, location} = location;
setFormData({...formData, city, state, location})
}
const {city, state, country} = formData;
return (
<form>
<button onClick={handleOnClick}/>
<label>
City:
<input name="city" value={city} onChange={handleOnChange}/>
</label>
<label>
State:
<input name="state" value={state} onChange={handleOnChange}/>
</label>
<label>
Country:
<input name="city" value={country} onChange={handleOnChange}/>
</label>
</form>
)
}
const mapStateToProps = (state) => {
location: state.location
}
export default connect(mapStateToProps, {setLocation})(LocationForm);
Problem:
From what I could figure from the console.log()
in the handleOnClick
, the state of the location
object passed down from the redux store still has empty string as values for the keys(city, state, country). But the state in the redux chrome devtool does show that the state for location has changed and they have the right values. How come the location object in the component's props does not reflect that? Do I need to use a useEffect
hook to update the location
object in the component's props?
Thanks in advance.
Upvotes: 0
Views: 398
Reputation: 22304
You are passing a mapDispatchToProps anonymous object to connect
, but not using it in the component. Instead you were calling setLocation()
as a normal function without dispatch. You need to call the prop, not the imported function like this:
const LocationForm = ({location, setLocation}) => {
...
setLocation()
...
export default connect(mapStateToProps, {setLocation})(LocationForm);
import {useSelector, useDispatch} from 'react-redux'
...
const LocationForm = () => {
const location = useSelector((state) => state.location)
const dispatch = useDispatch()
...
const handleOnClick => {
dispatch(setLocation) // if setLocation = (dispatch) => ...
// dispatch(setLocation()) // if setLocation = () => (dispatch) =>
...
Upvotes: 0
Reputation: 22474
If you want to monitor changes of the location
property, you have to use a hook, here is an example:
import React, {useState, useEffect} from 'react';
import {connect} from 'react-redux';
import {setLocation} from "../actions/location.js";
const LocationForm = ({location}) => {
..
useEffect(() => {
console.log(location)
const {city, state, location} = location;
setFormData({...formData, city, state, location})
}, [location]);
const handleOnClick = () => {
setLocation();
}
..
}
The function passed as the first argument to useEffect
is called every time any of the elements of the array passed as the second argument change.
Here, each time location
changes, setFormData
is called with the new values in location
.
Upvotes: 2