Search code examples
reactjsreact-nativereact-native-router-fluxreact-context

Using Context API with react-native-router-flux resets the stack when I use setState() on the App component


I am using coding a React Native app. I decided to use the Context API of React to pass the global state to the children components, and pass some callbacks as well, which will call setState() in the App component. I use react-native-router-flux to navigate between components (pages). I don't have any problem by reading the App state but when I setState(), I get automatically back to the initial Component page. setState() is well called.

I already tried to return false in ComponetShouldUpdate() of the router without success...

export default class Routes extends Component { render() { return ( ` ) }}

Here is my App class, where I store the globalState.

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.clearData = this.clearData.bind(this)
    this.storeData = this.storeData.bind(this)

    this.state = {
      isReady: false,
      calendar: [],
      best: 0,
      bestPercent: "0 %",
      clearData: this.clearData,
      storeData: this.storeData,
    };
  }

  clearData = async () => {
    const asyncStorageKeys = await AsyncStorage.getAllKeys();
    if (asyncStorageKeys.length > 0) {
      await AsyncStorage.clear();
    }
    this.setState({
      best: 0,                           //
      calendar: [],                      //
      bestString: secondsToHms(0),       //
      bestPercent: getPercent(0),        // If I delete these lines, react-native-router-flux won't reset
    }); 
    }

  storeData = async (result) => {
    let today = new Date();
    let data = {}
    data.date = today
    data.result = result
    let calendar = this.state.calendar;
    let foundIndex = calendar.findIndex(element => sameDay(new Date(element.date), today));
    if (foundIndex === -1) {
        calendar.push(data)
    } else {
        if (calendar[foundIndex].result < result) {
            calendar[foundIndex].result = result;
        }
    }

    try {
        await AsyncStorage.setItem('calendar', JSON.stringify(calendar))
        this.state.calendar = calendar;
        if (result > this.state.best) {
            await AsyncStorage.setItem('best', result.toString())

            this.setState(state => ({               //
              best: result || 0,                    //
              bestString: secondsToHms(result),     //
              bestPercent: getPercent(result),      //
            }));                                    //  If I delete these lines, react-native-router-flux won't reset

        }
    } catch (e) {}
    }

  async componentDidMount() {
    await Font.loadAsync({
      Roboto: require('native-base/Fonts/Roboto.ttf'),
      Chintok: require('native-base/Fonts/Chintok.ttf'),
      Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
      Minecraft: require('native-base/Fonts/Minecraft.ttf'),
      ...Ionicons.font,
    });
    await this.loadBest();
    await this.loadCalendar();    
    this.setState({ isReady: true });
  }

  render() {
    if (!this.state.isReady) {
      return <AppLoading />;
    }

    return (
      <GlobalStateContext.Provider value={this.state}>
        <StyleProvider style={getTheme(material)}>
          <Container >
            <Routes />
          </Container>
        </StyleProvider>
      </GlobalStateContext.Provider>
    );
  }
}

Solution

  • I use now react-navigation, since react-native-router-flux is not actively maintained