【问题标题】:React Native : update context throw "Cannot update during an existing state transition"React Native:更新上下文抛出“在现有状态转换期间无法更新”
【发布时间】:2021-02-08 10:53:36
【问题描述】:

我有一个反应原生应用程序,我正在尝试在自定义上下文中更新日期。

主题上下文

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 && <DateTimePicker
                ...
                onChange={(event, selectedDate) => this.onChange(event, selectedDate)}>
        </DateTimePicker>}</>
        )
    }
}

我使用 lib 'DateTimePicker' 选择日期并绑定 onChange 以更新上下文。此选择器位于模态框上。

所以当触发 DateTimePicker 的onChange 函数时会出现警告。错误出现在App.tsxsetState 上(在setDate 中)

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

你知道如何纠正这个错误吗?

编辑:

我正在使用 UI Kitten 库中的 Modal 组件。我切换到 react native Modal 并且错误消失了。似乎错误来自图书馆。对不起

提前感谢您的帮助, 西尔文

【问题讨论】:

  • 有这方面的消息吗?
  • @Konstantin 我,我编辑了我的问题,错误最终似乎来自用于 Modal 组件的库。

标签: react-native expo react-context react-native-ui-kitten


【解决方案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 做同样的事情。

【讨论】:

  • 我,谢谢你的回答。我试着按照你说的做,但我有同样的错误。错误发生在 App 组件内部,而不是 Picker 内部。所以我认为错误在于应用程序类
  • 我的理解是您指向了您的选择器中的setDate 行。我不知道哪一行给你带来了问题,所以请相应地更新你的问题。
  • 我在问题的最后说:“所以当触发 DateTimePicker 的 onChange 函数时会出现警告。错误出现在 App.tsx 的 setState 上(在 setDate 中)”。还不清楚吗?
  • 我更新代码以查看究竟是哪一行引发了错误
  • 我又修改了你的代码,为什么你的fns在render里面?请将它们转换为方法(删除consts,您使用的是Class,而不是Functional 组件),将它们移到Render 之外,使用this 将它们传递到您的上下文中,并请告诉我结合它的结果加上以前的答案。
【解决方案2】:

我编辑了我的问题。错误最终似乎来自使用的库(ui kitten)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-31
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    相关资源
    最近更新 更多