从react-navigation自定义标头内部调用的函数,该函数使用钩子

时间:2020-02-05 20:45:29

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

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

因此,我将updateUser函数传递给具有navigation.setParams函数的标头。 在标题中,我从updateUsernavigation.state.params

第一次按-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函数外部调用钩子。

有没有适当的方法来解决?如果没有,什么解决方法?

1 个答案:

答案 0 :(得分:2)

我的解决方法#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函数中使用的所有变量,并使用更新后的navigation.setParams函数调用updateUser每当这些变量更改时:

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

尽管解决方案#2在代码上更简洁一些,但我个人更喜欢解决方案#1,因为第二种解决方案可能会导致不明显的错误,以防万一我们错过了在updateUser函数中使用的变量的添加,使用效果数组。