Home > other >  Why my child component did not get state update from parent component?
Why my child component did not get state update from parent component?

Time:02-22

Context

I'm trying to use google-map-react to show local bakery stores.

However, the line console.log(props); in my child component StoresGoogleMap prints storeLocations and stores as []. If I use below instead in my StoresGoogleMap component, the it is working:

{props.storeLocations.map((storeLocation) => (
              <Marker
                key={storeLocation.unique_store_name}
                lat={storeLocation.store_location_latitude}
                lng={storeLocation.store_location_longitude}
                store={storeLocation}
              />
            ))}

So I think here the problem is that the child component StoresGoogleMap is rendered with initial value in parent component SearchStoresPage, which is []. But not updated when parent component's state changed.

Any suggestion how to fix this?

Details

I have a parent component defined like this:

const SearchStoresPage = () => {

  const [state, setState] = React.useState<StateProperties>(
    {stores:[], storeLocations: []} 
  );

    React.useEffect(
      () => {
        searchStores()
            .then(
              response => {
                const locations : GoogleMapStoreLocation[] = response.map( 
                      (obj:TypeStore) => {
                        return (
                            {
                                store_id: obj['store_id'],
                                store_name: obj['store_name'],
                                unique_store_name: obj['unique_store_name'],
                                store_description: obj['store_description'],
                                store_website: obj['store_website'],
                                store_cell_number: obj['store_cell_number'],
                                store_email: obj['store_email'],
                                store_location: obj['store_location'],
                                store_location_latitude: obj['store_location_latitude'],
                                store_location_longitude: obj['store_location_longitude'],
                                show: false
                            } 
                        )
                    }
                  );
                setState({stores: response, storeLocations: locations});
              }
            )
            .catch(error => console.log(error));  
      }, 
      []
  );

  return (
    <div className="flex flex-row">
      <StoreList storeList = {state.stores}/>
      <StoresGoogleMap storeLocations = {state.storeLocations} stores = {state.stores} defaultCenter={[40.7831, -73.9712]}/>    
    </div>
  );
};

And I have a child component StoresGoogleMap defined like this:

const StoresGoogleMap = (props: StoresGoogleMapProps) => {

  const [storeLocations, setStoreLocations] = React.useState<GoogleMapStoreLocation[]>(props.storeLocations);

  React.useEffect(
      () => {
        console.log(props);
        setStoreLocations(props.storeLocations);
      }, 
      []
  );

  const onMarkerClick = (unique_store_name: string) => {
    ...
  };

    return (
      <div id="map" style={{ height: '100vh', width: '100%' }}>
          <GoogleMap
            defaultZoom={12}
            defaultCenter={props.defaultCenter}
            bootstrapURLKeys={{ key: process.env.REACT_APP_GOOGLE_MAP_API_KEY }}
            onChildClick={onMarkerClick}
          >
            {storeLocations.map((storeLocation) => (
              <Marker
                key={storeLocation.unique_store_name}
                lat={storeLocation.store_location_latitude}
                lng={storeLocation.store_location_longitude}
                store={storeLocation}
              />
            ))}
          </GoogleMap>
        
      </div>
    );
  
};

CodePudding user response:

So I think here the problem is that the child component StoresGoogleMap is rendered with initial value in parent component SearchStoresPage, which is []. But not updated when parent component's state changed. Any suggestion how to fix this?

A way to fix this is to fire useEffect in your child component when data in parent component changes --> By adding props.storeLocations as a dependency in StoresGoogleMap useEffect()

CodePudding user response:

Because you are passing empty array [] in your child component's useEffect so it runs only 1st time when it renders.

Now let's say your data was fetched hence child component will be re-rendered but your useEffect will not run again since you passed an empty array in the dependency.

So you can safely use props.storeLocations.map or remove [] from useEffect that will cause the useEffect run on every single render or if you really want to use state variable add props.storeLocations to your child useEffect dependency

  • Related