反应-从子组件更新状态不起作用

时间:2020-04-27 16:44:20

标签: javascript reactjs react-native

我正在玩一个React-Native项目,并且试图实现一个简单的下拉菜单。经过研究后,我决定使用this库来完成它。

我正在努力理解React中的引用,这就是我的意思:

我有一个简单的屏幕,该屏幕使用react-navigation在右上角显示一个带有下拉菜单的按钮:

export default function () {
 const nav = useNavigation();
 const [hideCompleted, setHideCompleted] = useState(false);

  useEffect(() => {
    nav.setOptions({
      headerRight: () => (
        <ContextMenu
          hideCompleted={hideCompleted}
          handleCompletedClicked={() => {
            setHideCompleted(!hideCompleted);
          }}
        />
      ),
    });
  }, []);
}

ContextMenu看起来像这样:

export default ({ hideCompleted, handleCompletedClicked }) => {
  let menuRef = useRef();

  const setMenuRef = (ref) => {
    menuRef.current = ref;
  };

  const handleHideCompleted = () => {
    menuRef.current.hide();
    handleCompletedClicked();
  };

  return (
    <View>
      <Menu
        ref={setMenuRef}
        button={<Button onPress={showMenu} />}>
        <MenuItem onPress={handleHideCompleted}>
          {hideCompleted ? 'Show' : 'Hide'} completed
        </MenuItem>
      </Menu>
    </View>
  );
};

问题很简单。每当我单击Hide completed时,它都起作用,但是第二次单击时却不起作用。我想我没有正确传递hideCompleted,或者当父项的状态更改时,没有重新渲染ContextMenu组件。

谢谢您的帮助:)

2 个答案:

答案 0 :(得分:0)

因为您正在useEffect内部渲染仅在安装(空[])上运行的组件,所以ContextMenu不再使用新的hideCompleted进行渲染。只需将其添加到依赖项数组


   useEffect(() => {
     nav.setOptions({
      headerRight: () => (
       <ContextMenu
        hideCompleted={hideCompleted}
        handleCompletedClicked={() => {
          setHideCompleted(!hideCompleted);
        }}
       />
      ),
     });
   }, [hideCompleted]);
  )

答案 1 :(得分:0)

最好的解决方案是使用回调设置状态。像这样:

setHideCompleted((prevHideCompleted) => !prevHideCompleted);

这样,您的useEffect不会在每次状态更新时再次运行。

 useEffect(() => {
    nav.setOptions({
      headerRight: () => (
        <ContextMenu
          hideCompleted={hideCompleted}
          handleCompletedClicked={() => {
            setHideCompleted((prevHideCompleted) => !prevHideCompleted);
          }}
        />
      ),
    });
  }, []);