简体   繁体   中英

Redux store state from React component's props does not reflect redux store's state value

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.

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 .

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);

I would also recommend to give a chance to hooks which might be easier to understand IMHO:
 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) => ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM