反应导航:正确在屏幕之间传递状态

时间:2019-10-03 07:39:54

标签: react-native react-navigation

我正在尝试在屏幕之间传递状态。 我遵循了 Passing parameters to routes我可以pass state从主屏幕切换到详细信息屏幕,但是当我尝试从pass back state从详细信息屏幕切换到主屏幕时,状态无法通过。

我在主屏幕中有一个同意按钮,当我check on the button并导航到详细信息屏幕时,button is checked(到目前为止很好)。

但是,如果我uncheck从“详细信息”屏幕上的按钮and navigate back to Home screen the state is still已选中`。

Try the code from expo

这是我的主屏幕代码:

const imageOn = require("./iconCheck.png");
const imageOff = require("./emptyCheck.png");

class HomeScreen extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
      agreeState: this.props.navigation.getParam('agreeServiceFromChild'),
    };
  }

  checkStateImage(){
    if(this.state.agreeState === undefined){this.setState({agreeState:false},()=>console.log(this.state.agreeState,'agreeState'))}
    if(this.state.agreeState === true){return(imageOn)}
    if(this.state.agreeState === false){return(imageOff)}
  }
  render() {
        const { navigation } = this.props;

    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Home Screen</Text>
        <CustomCheckBox
          onPress={() => this.setState({agreeState: !this.state.agreeState}, ()=> console.log (this.state.agreeState,'agreeState'))}
          onPressButton={() =>
            this.props.navigation.navigate('Details', {
              agreeServiceFromParent:this.state.agreeState,
            })
          }
          source={this.checkStateImage()}
          text='agree'
          buttonText='go to DetailScreen'

        />
      </View>
    );
  }
}

这是我的详细屏幕代码:

class DetailsScreen extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
      agreeState:this.props.navigation.getParam('agreeServiceFromParent'),
    };
  }

    checkStateImage(){
    if(this.state.agreeState === undefined){return(imageOff)}
    if(this.state.agreeState != undefined && this.state.agreeState === true){return(imageOn)}
    if(this.state.agreeState != undefined && this.state.agreeState === false){return(imageOff)}
  }

  render() {
    const { navigation } = this.props;
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Details Screen</Text>
         <CustomCheckBox
        onPress={() => this.setState({ agreeState: !this.state.agreeState}, ()=> console.log(this.state.agreeState,'agreeServiceFromChild childview'))}
        source={this.checkStateImage()}
        text="agree"
        onPressButton={() =>
            this.props.navigation.navigate('Home', {
              agreeServiceFromChild:this.state.agreeState,
            })
          }
        buttonText='go to HomeScreen'
      />
      </View>
    );
  }
}

1 个答案:

答案 0 :(得分:1)

与其将其放入构造函数中,不如将其放入componentDidMount()中。 PFB从expo snaack更新的代码ive。并且我使用了navigation.push来代替navigation.navigate,因为coz push总是在navigator stack的顶部进行隐式推送。

import React from 'react';
import { Button, View, Text, TouchableOpacity, Image } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';

const imageOn = require("./iconCheck.png");
const imageOff = require("./emptyCheck.png");

class HomeScreen extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
      agreeState: false,
    };
  }

  componentDidMount(){
    let stateOfBut = this.props.navigation.getParam('agreeServiceFromChild');
    this.setState({agreeState:stateOfBut})
  }

  checkStateImage(){
    if(this.state.agreeState === undefined){this.setState({agreeState:false},()=>console.log(this.state.agreeState,'agreeState'))}
    if(this.state.agreeState === true){return(imageOn)}
    if(this.state.agreeState === false){return(imageOff)}
  }
  render() {
        const { navigation } = this.props;

    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Home Screen</Text>
        <CustomCheckBox
          onPress={() => this.setState({agreeState: !this.state.agreeState}, ()=> console.log (this.state.agreeState,'agreeState'))}
          onPressButton={() =>
            this.props.navigation.navigate('Details', {
              agreeServiceFromParent:this.state.agreeState,
            })
          }
          source={this.checkStateImage()}
          text='agree'
          buttonText='go to DetailScreen'

        />
      </View>
    );
  }
}

class DetailsScreen extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
      agreeState:this.props.navigation.getParam('agreeServiceFromParent'),
    };
  }

    checkStateImage(){
    if(this.state.agreeState === undefined){return(imageOff)}
    if(this.state.agreeState != undefined && this.state.agreeState === true){return(imageOn)}
    if(this.state.agreeState != undefined && this.state.agreeState === false){return(imageOff)}
  }

  render() {
    const { navigation } = this.props;
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Details Screen</Text>
         <CustomCheckBox
        onPress={() => this.setState({ agreeState: !this.state.agreeState}, ()=> console.log(this.state.agreeState,'agreeServiceFromChild childview'))}
        source={this.checkStateImage()}
        text="agree"
        onPressButton={() =>
            this.props.navigation.push('Home', {
              agreeServiceFromChild:this.state.agreeState,
            })
          }
        buttonText='go to HomeScreen'
      />
      </View>
    );
  }
}

const CustomCheckBox = ({ onPress, source, text, onPressButton, buttonText }) => (
    <View
      style={{
        marginTop: 14,
        height: 100,
        width: 310,
        backgroundColor: "transparent",
        alignItems: "center",
        justifyContent: "flex-start",
      }}
    >
    <TouchableOpacity onPress={onPress}>
      <View
        style={{
          marginLeft: 7,
          flexDirection:'row',
          backgroundColor: "white",
          borderRadius: 10,
          alignItems: "center",
          justifyContent: "center"
        }}
      >
      <Image style={{ width: 21, height: 21 }} source={source} />
          <Text style={{ marginLeft: 8 }}>{text}</Text>

      </View>

      </TouchableOpacity>

      <Button title={buttonText} onPress={onPressButton}/>

    </View>
);

const RootStack = createStackNavigator({
  Home: HomeScreen,
  Details: DetailsScreen,
});

export default createAppContainer(RootStack);