cappycap
cappycap

Reputation: 29

How to successfully pass params between screens?

I have been reading a lot of answers on SO as well as GitHub issues trying to implement a solution, but have been unable to come up with a solution for this situation.

Here is a representation of my code:

class MeetingsScreen extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      upcomingMeeting: [],
      refreshing: false
    };
  }

  async handlePress() {
    const user = await AsyncStorage.getItem('User');
    this.props.navigation.navigate('WriteSummary', { id: user.id, type: 'submit' });
  }

  printUpcomingMeetings = () => {
    return (<View style={styles.meeting}>
            <Button
              containerStyle={styles.meetingButton}
              style={styles.meetingButtonText}
              onPress={() => this.handlePress(user.id)}
              Press me to write summary!
            </Button>
          </View>);
    }

  }

  render () {
    return (<View style={{flex:1}} key={this.state.refreshing}>
    { this.printUpcomingMeetings() }
    </View>);
  }
}

class WriteSummaryScreen extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      storageId: '',
      normalId: -1,
      type: '',
      curSummary: ''
    }
  }

  componentDidMount = () => {
    const { params } = this.props.navigation.state;
    const { id, type } = params ? params : null;
    const storageId = 'summary_' + id;
    this.setState({storageId:storageId});
    this.setState({normalId:id});
    this.setState({type:type});
    AsyncStorage.getItem(storageId).then((value) => this.setSkipValue(value));
  }

  async setSkipValue (value) {
    if (value !== null) {
      this.setState({ 'curSummary': value });
    } else {
      this.setState({ 'curSummary': '' });
    }
  }

  async saveSummary (text) {
    this.setState({'curSummary': text});
    await AsyncStorage.setItem(this.state.storageId, text);
  }

  async handleSubmit() {
    const user = await AsyncStorage.getItem('User');
    if (this.state.type === 'submit') {
      // post insert
      const postres = fetch (url + '/create-summary', {
        method: 'POST',
        body: JSON.stringify({
          AppointmentId: this.state.normalId,
          SummaryText: this.state.curSummary,
          UserId: user.Id
        }),
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        }
      })
      .catch((error) => {
        console.error(error);
      });
    } else {
      // post update
      const postres = fetch (url + '/update-summary', {
        method: 'POST',
        body: JSON.stringify({
          AppointmentId: this.state.normalId,
          SummaryText: this.state.curSummary,
          UserId: user.Id
        }),
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        }
      })
      .catch((error) => {
        console.error(error);
      });
    }
    this.props.navigation.navigate('Meetings');
  }

  render () {
    return <View style={{flex:1}}>
      <View>
        <View style={{height:25, backgroundColor: colors.vikingBlue}}></View>
        <View style={{height:30, backgroundColor: colors.white}}></View>
        <View style={{flexDirection:'row', backgroundColor: colors.white, alignItems:'center'}}>
          <View style={{width:5}}></View>
          <TouchableOpacity onPress={() => this.props.navigation.goBack()} activeOpacity={0.5}>
            <Image style={{width:30, height:30}} source={require('./assets/icons8-back-50.png')} />
          </TouchableOpacity>
          <View style={{width:10}}></View>
          <View style={{width:mainTitleWidth,textAlign:'center',alignItems:'center'}}>
            <Text style={{fontSize:22}}>Settings</Text>
          </View>
          <TouchableOpacity onPress={() => this.props.navigation.navigate('HelpModal')} activeOpacity={0.5}>
            <Image style={{width:30, height:30}} source={require('./assets/help.png')} />
          </TouchableOpacity>
        </View>
        <View style={{height:30, backgroundColor: colors.white}}></View>
      </View>
      <TextInput
      multiline
      numberOfLines={6}
      style={styles.summaryInput}
      onChangeText={text => saveSummary(text)}
      value={this.state.curSummary} />
      <Button
        containerStyle={styles.summaryButton}
        style={styles.summaryButtonText}
        onPress={this.handleSubmit()}>
        Submit
      </Button>
    </View>
  }
}

function HomeStack() {
  return (
    <Tab.Navigator
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Meetings" component={MeetingsScreen} />
        <Tab.Screen name="Topics" component={TopicsScreen} />
    </Tab.Navigator>
  );
}

export default class AppContainer extends React.Component {

  // Main rendering function. Always begins on the SplashScreen, which checks user login status and directs to Meetings. I left it out and the other Tab navigator screens for less clutter.

  render() {
    return (
        <NavigationContainer>
          <Stack.Navigator headerMode='none' initialRouteName='Splash'>
            <Stack.Screen name='Splash' component={SplashScreen} />
            <Stack.Screen name='Main' component={HomeStack} />
            <Stack.Screen name='WriteSummary' component={WriteSummaryScreen} />
          </Stack.Navigator>
        </NavigationContainer>
    );
  }
};

I get the error TypeError: undefined is not an object (evaluating '_this7.props.navigation.state.params)' after pressing the button on MeetingsScreen and navigating to WriteSummaryScreen.

What confuses me is the screen is navigated to, so the data should have been passed. What am I missing?

Upvotes: 0

Views: 59

Answers (3)

Ketan Ramteke
Ketan Ramteke

Reputation: 10675

You can access parametes like below if its class based component:

class WriteSummaryScreen extends React.Component {
     const {id, type} = this.props.route.params;
//........

for the functional component:

const WriteSummaryScreen =({navigation, route})=>{
    const {id, type} = route.params;

//..........
}

Upvotes: 1

cappycap
cappycap

Reputation: 29

What ended up working for me was the following:

const id = this.props.route.params.id;
const type = this.props.route.params.type;

Upvotes: 0

Mahdi
Mahdi

Reputation: 1405

You can access the params that you have passed from a screen using the getParam function.

so you can use this code:

const id = this.props.navigation.getParam("id");
const type = this.props.navigation.getParam("type");

Upvotes: 0

Related Questions