为什么我的子组件没有从父组件获得状态更新?

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

上下文

我正在尝试使用 google-map-react 来展示当地的面包店。

但是,我的子组件 StoresGoogleMap 中的行 console.log(props);storeLocationsstores 打印为 []。如果我在我的 StoresGoogleMap 组件中使用 below,它正在工作:

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

所以我认为这里的问题是子组件 StoresGoogleMap 在父组件 SearchStoresPage 中以初始值呈现,即 []。但是当父组件的状态改变时不更新。

有什么解决方法的建议吗?

详情

我有一个这样定义的父组件:

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

我有一个子组件 StoresGoogleMap 定义如下:

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

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?

解决此问题的一种方法是在父组件中的数据更改时在子组件中触发 useEffect --> 通过在 StoresGoogleMap useEffect() 中添加 props.storeLocations 作为依赖项

因为您在 child 组件的 useEffect 中传递了空数组 [],所以它 运行 只有第一次呈现。

现在假设您的数据已获取,因此 child 组件将是 re-rendered 但您的 useEffect 不会再次 运行 因为您在依赖项中传递了一个空数组。

因此您可以安全地使用 props.storeLocations.map 或从 useEffect 中删除 [] 但这会导致在每个渲染上出现 useEffect 运行,因此您可以将 props.storeLocations 添加到您的 child useEffect 依赖项中。 但我真的看不出使用 child 状态与道具相同的意义,如果你只是为了渲染目的使用它