简体   繁体   中英

App crashes after calling setState in static method

After calling setState in navigationOptions the App crashes. This only happens on an Android device. Below my crashing code.

import React, { Component } from 'react';
import {
  Button,
  View,
  Platform,
  Text
} from 'react-native';
import { HeaderBackButton } from 'react-navigation-stack';

export default class Edit extends Component {
  static navigationOptions = ({ navigation: { state } }) => {
    return {
      title: 'add',
      gesturesEnabled: !state.params.isEditing,
      headerBackTitle: 'back',
      headerLeft: !state.params.isEditing(
        <HeaderBackButton
          backTitleVisible
          onPress={() => state.params.goBack()}
          title={Platform.OS === 'ios' ? 'back' : null}
        />
      ),
      headerRight: (
        <View style={Platform.OS !== 'ios' && { padding: 12 }}>
          {state.params.isEditing ? (
            <Button onPress={() => state.params.finishEditing()} title="done" />
          ) : (
            <Button onPress={() => state.params.beginEditing()} title="edit" />
          )}
        </View>
      ),
    };
  };

  state = {
    isLoading: true,
    isEditing: false,
    alreadyScanned: true,
  };

  componentDidMount() {
    this.setInitialState();
  }

  setInitialState = () => {
    const {
      navigation: {
        setParams,
        state: { params },
      },
      navigation,
    } = this.props;

    setParams({
      isEditing: this.state.isEditing,
      finishEditing: this.finishEditing,
      beginEditing: this.beginEditing,
      canGoBack: params.goBack,
      goBack: navigation.goBack,
    });
  };

  beginEditing = async () => {
    this.setState({
      isEditing: true,
    });
    await this.props.navigation.setParams({
      isEditing: true,
    });
  };

  finishEditing = async () => {
    this.setState({ isEditing: false });
    await this.props.navigation.setParams({
      isEditing: false,
    });
  };

  render() {
    const {isEditing} = this.state;
    return (
      <View
        style={{
          flex: 1,
          backgroundColor: isEditing ? 'green' : 'red'
        }}>
        <Text>is editing: {isEditing}</Text>
      </View>
    );
  }
}

I'm not quite sure why this code makes my app crash, because it did work before.

Expo Snack can't resolve the react-navigation module for some reason.. So here is my crashing code.

Project dependencies

  "dependencies": {
    "expo": "^35.0.0",
    "expo-asset": "~7.0.0",
    "expo-barcode-scanner": "~7.0.0",
    "expo-camera": "~7.0.0",
    "expo-constants": "~7.0.0",
    "expo-font": "~7.0.0",
    "expo-localization": "~7.0.0",
    "expo-permissions": "~7.0.0",
    "react": "16.11.0",
    "react-dom": "16.11.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",
    "react-native-elements": "^1.2.6",
    "react-native-gesture-handler": "~1.3.0",
    "react-navigation": "^4.0.10",
    "react-navigation-stack": "^1.10.3",
  }

Environment

You should validate this.props.navigation before setting the params.

import React, { Component } from 'react';
import {
  Button,
  View,
  Platform,
  Text
} from 'react-native';
import { HeaderBackButton } from 'react-navigation-stack';

export default class Edit extends Component {
  static navigationOptions = ({ navigation: { state } }) => {
    return {
      title: 'add',
      gesturesEnabled: !state.params.isEditing,
      headerBackTitle: 'back',
      headerLeft: !state.params.isEditing(
        <HeaderBackButton
          backTitleVisible
          onPress={() => state.params.goBack()}
          title={Platform.OS === 'ios' ? 'back' : null}
        />
      ),
      headerRight: (
        <View style={Platform.OS !== 'ios' && { padding: 12 }}>
          {state.params.isEditing ? (
            <Button onPress={() => state.params.finishEditing()} title="done" />
          ) : (
            <Button onPress={() => state.params.beginEditing()} title="edit" />
          )}
        </View>
      ),
    };
  };

  state = {
    isLoading: true,
    isEditing: false,
    alreadyScanned: true,
  };

  componentDidMount() {
    this.setInitialState();
  }

  setInitialState = () => {
    if(this.props.navigation){
      const {
        navigation: {
          setParams,
          state: { params },
        },
        navigation,
      } = this.props;

      setParams({
        isEditing: this.state.isEditing,
        finishEditing: this.finishEditing,
        beginEditing: this.beginEditing,
        canGoBack: params.goBack,
        goBack: navigation.goBack,
      });
    }
  };

  beginEditing = async () => {
    this.setState({
      isEditing: true,
    });
    await this.props.navigation.setParams({
      isEditing: true,
    });
  };

  finishEditing = async () => {
    this.setState({ isEditing: false });
    await this.props.navigation.setParams({
      isEditing: false,
    });
  };

  render() {
    const { isEditing } = this.state;
    return (
      <View
        style={{
          flex: 1,
          backgroundColor: isEditing ? 'green' : 'red',
          justifyContent: 'center',
          alignItems: 'center'
        }}>
        <Text>is editing: {isEditing}</Text>
      </View>
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM