React Native: выбрасывание контекста обновления «Невозможно обновить во время существующего перехода состояния»

#react-native #expo #react-context #react-native-ui-kitten

#react-native #expo #реагировать-контекст #react-native-ui-kitten

Вопрос:

У меня есть приложение react native, и я пытаюсь обновить дату в пользовательском контексте.

Тематический текст

 export const ThemeContext = React.createContext({
    theme: 'dark',
    toggleTheme: () => { },
    date: new Date(),
    setDate: (date: Date) => { } 
});
 

Базовый контекст с датой и функцией для ее обновления

App.tsx

 export default class App extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      theme: 'dark',
      date: new Date()
    };
  }

  render() {
    const { theme, date } = this.state;
    const currentTheme = themes[theme];

    const toggleTheme = () => {
      const nextTheme = theme === 'light' ? 'dark' : 'light';
      this.setState({ theme: nextTheme });
    };

    const setDate = (date: Date) => {
      // ERROR is raised HERE
      this.setState({date: date});
    }

    return (
      <>
        <IconRegistry icons={EvaIconsPack} />
        <ThemeContext.Provider value={{ theme, toggleTheme, date, setDate }}>
          ...
        </ThemeContext.Provider>
      </>
    );
  }
}
 

Я просто задаю состояние с датой и создаю функцию setDate. Я включил свое приложение в контекстный провайдер.

Средство выбора

 class PickerContent extends React.Component<{}, ContentState> {
    static contextType = ThemeContext;

    constructor(props: {} | Readonly<{}>) {
        super(props);
        let currentMode = 'date';
        let show = false;

        if (Platform.OS === 'ios') {
            currentMode = 'datetime';
            show = true;
        }

        this.state = {
            date: new Date(),
            mode: currentMode,
            show: show
        };
    }

    setMode(currentMode: string) {
        this.setState({ mode: currentMode, show: true });
    };

    onChange(_event: any, selectedDate: Date) {
        const currentDate = selectedDate || this.state.date;
        // I update the context here
        this.context.setDate(currentDate);
        
        this.setState({date: currentDate, show: Platform.OS === 'ios'})
    }

    render() {
        const {show, date, mode } = this.state;
        const color = 'dark';

        return (
            <>
            ...
            {show amp;amp; <DateTimePicker
                ...
                onChange={(event, selectedDate) => this.onChange(event, selectedDate)}>
        </DateTimePicker>}</>
        )
    }
}
 

Я использую библиотеку ‘DateTimePicker’, чтобы выбрать дату и привязать onChange для обновления контекста. Этот сборщик находится на модальном.

Таким образом, предупреждение появляется, когда onChange запускается функция DateTimePicker . Ошибка находится в setState of App.tsx (в setDate)

Warning: Cannot update during an existing state transition (such as within 'render'). Render methods should be a pure function of props and state.

Знаете ли вы, как исправить эту ошибку?

Редактировать :

Я использовал модальный компонент из библиотеки пользовательского интерфейса Kitten. Я переключаюсь на модальный режим react native, и ошибка исчезла. Похоже, что ошибка исходит из библиотеки. извините

заранее благодарю вас за помощь, Сильвен

Комментарии:

1. Есть какие-нибудь новости по этому поводу?

2. @Konstantin Я, я отредактировал свой вопрос, ошибка, наконец, кажется, исходит из библиотеки, используемой для модального компонента.

Ответ №1:

Если вы используете компонент класса, что вы можете сделать, так это переместить контекстное обновление fn внутрь componentDidUpdate . Вы просто сравниваете свои состояния, если ваше состояние изменилось, вы обновляете свой контекст новым значением. Что-то вроде:

 componentDidUpdate(prevProps, prevState) {
  if (prevState.date !== this.state.date) {
    this.context.setDate(this.state.date);
  }
}

onChange(_event: any, selectedDate: Date) {
    const currentDate = selectedDate || this.state.date;
    
    this.setState({date: currentDate, show: Platform.OS === 'ios'})
}
 

Таким образом, вы не обновляете свой контекст во время рендеринга.

Если вы реорганизуете этот компонент в функциональный, вы сможете сделать то же самое, используя useEffect .

Комментарии:

1. Я, спасибо за ваш ответ. Я пытался сделать то, что вы сказали, но у меня та же ошибка. Ошибка, которая возникает внутри компонента приложения, а не средства выбора. Поэтому я думаю, что ошибка связана с классом приложения

2. Насколько я понимаю, вы указали на строку setDate внутри вашего средства выбора. Я не могу знать, какая строка вызывает у вас проблему, поэтому, пожалуйста, соответствующим образом обновите свой вопрос.

3. В конце своего вопроса я сказал: «Итак, предупреждение появляется, когда запускается функция onChange DateTimePicker. Ошибка находится в setState App.tsx (в setDate) «. разве это не ясно?

4. Я обновляю код, чтобы увидеть, какая именно строка вызвала ошибку

5. Я снова пересмотрел ваш код, почему у вас есть fns внутри рендеринга? Пожалуйста, преобразуйте их в методы (удалите consts , вы используете класс, а не функциональный компонент), переместите их за пределы рендеринга, передайте их с помощью this в ваш контекст и, пожалуйста, сообщите мне результат объединения этого и предыдущего ответа.

Ответ №2:

Я отредактировал свой вопрос. Ошибка, наконец, кажется, исходит из используемой библиотеки (ui kitten).