【问题标题】:Call function, which uses hooks, from inside react-navigation custom header从 react-navigation 自定义标头内部调用使用钩子的函数
【发布时间】:2020-02-05 20:45:29
【问题描述】:

我有一个用 React Hooks 编写的屏幕。 在屏幕上,我在 react-navigation 标题中有一个自定义按钮。通过按下按钮,我需要调用函数updateUser,它使用来自状态的值(例如userName)。

所以我将updateUser 函数传递给带有navigation.setParams 函数的标头。 在标题中,我从navigation.state.params 调用updateUser

在第一次按下时 - userName 值是正确的。但是如果我再从组件内部更改值userName - 当我按下按钮时,函数内部的值保持不变。

下面是代码示例:

const ProfileScreen = ({navigation}) => {
 const [userName, setUserName] = useState('John');

  useEffect(() => {
    navigation.setParams({
      updateUser,
    });
  }, [])

  const updateUser = () => {
    console.log('userName', userName);
  }

  return (...)
};
ProfileScreen.navigationOptions = ({navigation}) => ({
  headerRight: () => {
    const {params = {}} = navigation.state;
    return (
      <TouchableOpacity onPress={() => params.updateUser()}>
        <Text>Update user</Text>
      </TouchableOpacity>
    );
  },
});

我认为发生这种情况是因为标头超出了组件范围并且没有获得更新的状态值。 React 还有一条规则,规定不要在 React 函数之外调用钩子。

有什么合适的方法解决吗?如果没有,解决方法是什么?

【问题讨论】:

    标签: reactjs react-native react-navigation react-hooks


    【解决方案1】:

    我的解决方法 #1 是再使用一个 useState,它会持续跟踪是否按下了更新按钮。

    所以在按下按钮时的标题中,我们将isUpdateButtonPressed 设置为true。然后在组件中我们观察该变化,如果它发生变化 - 我们调用updateUser。这样,updateUser 函数内部的状态是正确的。

    const ProfileScreen = ({navigation}) => {
      const [userName, setUserName] = useState('John');
      const [isUpdateButtonPressed, setIsUpdateButtonPressed] = useState(false);
    
      useEffect(() => {
        navigation.setParams({
          setIsUpdateButtonPressed,
        });
      }, [])
    
      useEffect(() => {
        if (isUpdateButtonPressed) {
          updateUser();
          setIsUpdateButtonPressed(false);
        }
      }, [isUpdateButtonPressed]);
    
      const updateUser = () => {
        console.log('userName', userName);
      }
    };
    ProfileScreen.navigationOptions = ({navigation}) => ({
      headerRight: () => {
        const {params = {}} = navigation.state;
        return (
          <TouchableOpacity onPress={() => params.setIsUpdateButtonPressed(true)}>
            <Text>Update user</Text>
          </TouchableOpacity>
        );
      },
    });
    

    我的解决方法 #2 是使用 useEffect 来监视 updateUser 函数中使用的所有变量,并在每次这些变量发生变化时使用更新的 updateUser 函数调用 navigation.setParams

      useEffect(() => {
        navigation.setParams({
          updateUser,
        });
      }, [userName])
    

    虽然解决方案 #2 的代码更简洁,但我个人更喜欢解决方案 #1,因为第二个解决方案可能会导致不明显的错误,以防我们错过添加一些变量,用于 updateUser 函数,到 useEffect大批。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-28
      • 2021-01-16
      • 1970-01-01
      • 2019-08-02
      • 2021-02-23
      • 1970-01-01
      • 2021-09-05
      • 1970-01-01
      相关资源
      最近更新 更多