React 上下文不在组件之间共享

React context not shared between components

我在两个组件之间使用了一个反应上下文,但是当我在子 filtersBar 组件中设置这个上下文的值时,它不会在第二个子地图组件中更新或使用效果。

上下文提供者

const SearchContext = createContext();

const SearchContextProvider = ({children}) => {
const [contextValue, setContextValue] = useState(null);            
    return (
    <SearchContext.Provider value={[contextValue, setContextValue]}>
        {children}
    </SearchContext.Provider>
);

index.js

 <SearchContextProvider>
    <FiltersBar/>
      <Map/>
    </SearchContextProvider>

Filtersbar.js

const FiltersBar = () => {
        const [searchContext,setSearchContext] = useContext(SearchContext);
        const [searchLocationResult, setsearchLocationResult] = useState(null);
        const [inputSearchLocation, setinputSearchLocation] = useState("");
  
 useEffect(() => {
// stuff
                 searchContext.autocompleteLocation = [46.6, 8.5]
              setSearchContext(searchContext)

        }, [searchLocationResult, inputSearchLocation]);

Map.js

const Map = () => {
  
    const [searchContext, setSearchContext] = useContext(SearchContext);


    useEffect(() => {
      console.log("use effect map"+JSON.stringify(searchContext))
    }, [searchContext]);

我从来没有看到这个使用效果图控制台日志消息。我错过了什么?

因为这个

useEffect(() => {
  /// stuff
  setSearchContext(searchContext) // ----> here
}, [searchLocationResult, inputSearchLocation]);

searchContext 永远不会改变。它始终为空,您始终将 null 设置为 setSearchContext 函数。 也许你只会在重新加载或组件初始化时得到第一个 console.log 就像 use effect mapnull

如果您显示的代码是您真实代码的准确表示,那么问题是您正在改变状态,而不是创建新状态。当您设置状态时,React 会在之前的状态和之后的状态之间执行 ===。它看到它们是同一个对象,所以它认为什么都没有改变,它什么也不做。

所以不是这个:

searchContext.autocompleteLocation = [46.6, 8.5]
setSearchContext(searchContext)

这样做:

const newState = {
  ...searchContext,
  autocompleteLocation: [46.6, 8.5]
}
setSearchContext(newState);

React hook 与 Class 组件中的 React state 有点不同。 React hook 仅当它是新对象时才考虑状态变化,你应该在更新状态时创建新对象。

您可以更新 FiltersBar 的 useEffect 如下: Filtersbar.js

const FiltersBar = () => {
        ...
 useEffect(() => {
// stuff
    setSearchContext({...searchContext, autocompleteLocation: [46.6, 8.5]})

}, [searchLocationResult, inputSearchLocation]);