React Navigation 5 headerRight按钮函数调用没有获得更新状态

Dan*_*Dan 5 react-native react-navigation react-navigation-v5

在以下简化示例中,用户使用 TextInput 更新标签状态,然后单击标题中的“保存”按钮。在提交函数中,当请求标签状态时,它返回原始值“”而不是更新后的值。

需要对导航 headerRight 按钮进行哪些更改才能解决此问题?

注意:当“保存”按钮位于渲染视图中时,一切都会按预期工作,只是当它位于标题中时则不然。

import React, {useState, useLayoutEffect} from 'react';
import { TouchableWithoutFeedback, View, Text, TextInput } from 'react-native';

export default function EditScreen({navigation}){
  const [label, setLabel] = useState('');

  useLayoutEffect(() => {
      navigation.setOptions({
        headerRight: () => (
          <TouchableWithoutFeedback onPress={submit}>
            <Text>Save</Text>
          </TouchableWithoutFeedback>
        ),
      });
    }, [navigation]);

  const submit = () => {
    //label doesn't return the updated state here
    const data = {label: label}
    fetch(....)
  }

  return(
    <View>
      <TextInput onChangeText={(text) => setLabel(text) } value={label} />  
    </View>
  )

}
Run Code Online (Sandbox Code Playgroud)

Gur*_*ran 9

标签应该作为 useLayouteffect 的依赖项传递,这将使钩子在更改时运行

  React.useLayoutEffect(() => {
      navigation.setOptions({
        headerRight: () => (
          <TouchableWithoutFeedback onPress={submit}>
            <Text>Save</Text>
          </TouchableWithoutFeedback>
        ),
      });
    }, [navigation,label]);
Run Code Online (Sandbox Code Playgroud)


Dan*_*Dan 5

尽管我想让该解决方案更适用于具有许多文本输入的屏幕,但古鲁帕兰的答案对于这个问题来说是正确的。

为了实现这一点,我添加了一个名为“保存”的附加状态,单击“完成”时该状态设置为 true。这会触发 useEffect 钩子被调用,从而触发提交。

export default function EditScreen({navigation}){
  const [label, setLabel] = useState('');
  const [saving, setSaving] = useState(false);

  useLayoutEffect(() => {
      navigation.setOptions({
        headerRight: () => (
          <TouchableWithoutFeedback onPress={() => setSaving(true)}>
            <Text>Done</Text>
          </TouchableWithoutFeedback>
        ),
      });
    }, [navigation]);

    useEffect(() => {
      // Check if saving to avoid calling submit on screen unmounting
      if(saving){
        submit()
      }
    }, [saving]);

    const submit = () => {
      const data = {label: label}
      fetch(....)
    }

    return(
      <View>
        <TextInput onChangeText={(text) => setLabel(text) } value={label} />  
      </View>
    )

}
Run Code Online (Sandbox Code Playgroud)