Заголовок React Navigation 5, вызываемая функция правой кнопки не получает обновленные состояния

В следующем упрощенном примере пользователь обновляет состояние метки с помощью TextInput, а затем нажимает кнопку «Сохранить» в заголовке. В функции отправки, когда запрашивается состояние метки, она возвращает исходное значение, а не обновленное значение.

Какие изменения необходимо внести в заголовок навигации Правая кнопка, чтобы исправить эту проблему?

Примечание. Когда кнопка «Сохранить» находится в режиме рендеринга, все работает так, как ожидалось, только не в заголовке.

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>
  )

}

person Dan    schedule 07.06.2020    source источник


Ответы (2)


Метка должна быть передана как зависимость для useLayouteffect, что заставит ловушку запускаться при изменениях.

  React.useLayoutEffect(() => {
      navigation.setOptions({
        headerRight: () => (
          <TouchableWithoutFeedback onPress={submit}>
            <Text>Save</Text>
          </TouchableWithoutFeedback>
        ),
      });
    }, [navigation,label]);
person Guruparan Giritharan    schedule 08.06.2020

Ответ Гурупарана на вопрос правильный, хотя я хотел сделать решение более удобным для экранов с большим количеством TextInputs.

Для этого я добавил дополнительное состояние, называемое сохранением, для которого устанавливается значение 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>
    )

}
person Dan    schedule 08.06.2020