最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - Why this zustand selector is causing 'Maximum update depth exceeded'? - Stack Overflow

programmeradmin1浏览0评论

I have this zustand store

interface PropertyStore {
    cache: Record<PropertyData["id"], PropertyData>;
    fetchProperty: (propertyId: PropertyData["id"]) => StoreResponse<undefined>;
    searchProperties: (filter: PropertySchemaFilter) => StoreResponse<undefined>;
    createProperty: (newPropertyData: CreatePropertyData) => StoreResponse<undefined>;
    updateProperty: (propertyId: PropertyData['id'], updatedProperty: UpdatePropertyData) => StoreResponse<undefined>;
}

export const usePropertyStore = create<PropertyStore>((set, get) => { 
    const cacheProperties = (properties: PropertyData[]) => {
        const { cache } = get();
        const cacheCopy = { ...cache };

        properties.forEach((property) => {
            cacheCopy[property.id] = property;
        });
    
        set({ cache: cacheCopy });
    };

    const newPropertyHandler = (newProperty: PropertyData) => {
        console.log(`event -> [${WsEvent.NewProperty}] ${newProperty.address} `);
        cacheProperties([newProperty]);
    }
    const updatedPropertyHandler = (updatedProperty: PropertyData) => {
        console.log(`event -> [${WsEvent.UpdatedProperty}] ${updatedProperty.address} `);
        cacheProperties([updatedProperty]);
    }
    propertiesSubscribe(newPropertyHandler, updatedPropertyHandler);

    return {
        cache: {},
        fetchProperty: async (propertyId: PropertyData["id"]) => {
            const { data: property, error } = await getProperty(propertyId);

            if (error) {
                return { error };
            }

            if (property) {
                cacheProperties([property]);
            }

            return { data: undefined };
        },
        searchProperties: async (filter) => {
            console.log(`propertyStore -> searchProperties ${JSON.stringify(filter)}`)

            const { error, data } = await getProperties(filter);

            if (error) {
                return { error };
            }

            cacheProperties(data);
            return { data: undefined };
        },
        createProperty: async (newPropertyData) => {
            const { error } = await createProperty(newPropertyData);
            return error ? { error } : { data: undefined };
        },
        updateProperty: async (propertyId, updatedProperty) => {
            const { error } = await updateProperty(propertyId, updatedProperty);
            return error ? { error } : { data: undefined };
        },
    };
})

A component that accesses the data by

const properties = usePropertyStore((store) => // <- line 31
  Object.values(store.cache).filter((property) =>
    propertyCompliesFilter(property, propertiesFilter) // <- line 33
  )
);
const searchProperties = usePropertyStore((store) => store.searchProperties);

//searchProperties effect
useEffect(() => {
  console.log(`App -> effect [searchProperties]`);

  setSearchingProperties(true);
  setSearchPropertiesError(undefined);

  searchProperties(propertiesFilter)
    .then(({ error }) => {
      if (error) {
        setSearchPropertiesError(error);
      }
    })
    .finally(() => {
      setSearchingProperties(false);
    });
}, [propertiesFilter, searchProperties]);

And renders the data by

{properties.map((property) => (
  <Marker
    key={property.id}
    position={property.coordinates}
    icon={getIconForProperty(property)}
  >
    <Popup>
      {property.id}: {property.address}
      <button
        type="button"
        onClick={() => openViewPropertyModal(property.id)}
      >
        Open details
      </button>
    </Popup>
  </Marker>
))}

The logs are

Warning: The result of getSnapshot should be cached to avoid an infinite loop at App (http://localhost:5173/src/App.tsx?t=1737126342124:33:25)

App -> effect [searchProperties]
propertyStore -> searchProperties {"deleted":false}
realtorMapService -> getProperties
App -> effect [searchProperties]
propertyStore -> searchProperties {"deleted":false}
realtorMapService -> getProperties

(the effect seems to execute twice before the error)

Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

what is causing the infinite loop?

发布评论

评论列表(0)

  1. 暂无评论