redux 来自存储区的更新值在函数内部不会更改

dfty9e19  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(129)

我有一些功能组件。在组件中我从redux存储中获取值(我使用redux工具包)。同时我在这个组件中有处理程序。
通过RTK查询向API发出请求后,存储中设置的变量值。因此,该变量首先具有默认值,然后更改为API中的值。
问题:redux存储中的变量值未在处理程序内更新。

const SomeContainer = () => {
    const dispatch = useDispatch();

    const variableFromStore = useSelector(someSelectors.variableFromStore);
    console.log(variableFromStore)**// correct value (updated)**

    const handleSomeAction = () => {
        console.log(variableFromStore)**// default value of init store (not updated)**
    };

    return <SomeComponent onSomeAction={handleSomeAction} />;
};

某些组件

const SomeComponent = (props) => {
    const { list, onSomeAction } = props;

    const moreRef = useRef(null);

    const loadMore = () => {
        if (moreRef.current) {
            const scrollMorePosition = moreRef.current.getBoundingClientRect().bottom;
            if (scrollMorePosition <= window.innerHeight) {
                onSomeAction(); // Call handler from Container
            }
        }
    };

    useEffect(() => {
        window.addEventListener('scroll', loadMore);
        return () => {
            window.removeEventListener('scroll', loadMore);
        };
    }, []);

    return (
        ...
    );
};

怎么可能,我有什么不明白的?)

41zrol4v

41zrol4v1#

问题是您无意中创建了一个围绕原始版本handleSomeAction的闭包:

useEffect(() => {
  window.addEventListener('scroll', loadMore);
  return () => {
    window.removeEventListener('scroll', loadMore);
  }
}, []);

此处的dependencies数组为空,这意味着此效果仅在组件第一次挂载时运行,因此在组件挂载时捕获loadMore的值(组件挂载时onSomeAction本身捕获onSomeAction值)。
“简单的解决方法”是将loadMore指定为效果的依赖项:

useEffect(() => {
  window.addEventListener('scroll', loadMore);
  return () => {
    window.removeEventListener('scroll', loadMore);
  }
}, [loadMore]);

但是!这将产生一个新的问题-handleSomeAction在每个渲染上都被重新创建,所以你的效果现在也会在每个渲染上运行!
因此,在不知道您 * 实际 * 尝试做什么的更多细节的情况下,我将使用ref来存储对onSomeAction的引用,并将loadMore内联到您的效果中:

// A simple custom hook that updates a ref to whatever the latest value was passed
const useLatest = (value) => {
  const ref = useRef();
  ref.current = value;

  return ref;
}

const SomeComponent = (props) => {
  const { list, onSomeAction } = props;

  const moreRef = useRef(null);
  const onSomeActionRef = useLatest(onSomeAction);

  useEffect(() => {
    const loadMore = () => {
      if (!moreRef.current) return;

      const scrollMorePosition = moreRef.current.getBoundingClientRect().bottom;
      if (scrollMorePosition <= window.innerHeight) {
          onSomeActionRef.current();
      }
    }

    window.addEventListener('scroll', loadMore);
    return () => window.removeEventListener('scroll', loadMore);
  }, []);

  return (
      ...
  );
};

相关问题