如何在 React Navigation 5 中将组件的 "this.state" 传递给屏幕

How to pass "this.state" of a Component to a Screen in React Navigation 5

我是 React Native 的新手,刚开始学习 ReactNavigation。

我正在使用的应用程序旨在在您玩棋盘游戏时跟踪玩家和分数。这是 App.js:

的代码
import * as React from 'react'; 
import {Component} from 'react';
import { StyleSheet, Text, View, Button, Alert } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { create StackNavigator } from '@react-navigation/stack';
import { Player } from './player';


const Stack = createStackNavigator();


export default class BoardGameApp extends Component{
  constructor(props){
      super(props);
      this.state={ playerTable:[] }
  }


  render(){

    let numOfPlayers = 4
    const totNumOfTerritories = 48

    return (

      <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
            <Stack.Screen name="Home" component={HomeScreen} />
            
        </Stack.Navigator>
      </NavigationContainer>
    );
  }
}



function HomeScreen(){
  
  return(
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button title="Add a new Player" onPress={
          () => this.setState({ playerTable: [
              ...this.state.playerTable,
              { playerName: "whatever"},
           ]
          })}>
      </Button>

      /* this is commented
      {this.state.playerTable.map(
        function(player) {
          return <Player territories={totNumOfTerritories / numOfPlayers} />;
        }
      )}  here the comment ends */

    </View>
  );
}
 

所以基本上应该发生的是,每当我按下按钮时,一个由 {playerName: "whatever"} 组成的对象应该被添加到 BoardGameApp 状态中存在的 PlayerTable[] 数组,然后我随后我要做的是映射这个数组并为数组中存在的每个对象 {playerName: "whatever"} 渲染一个 Player 组件。当所有这些都发生在 App 组件内部而不使用屏幕时,一切都很好,但当然它看起来很糟糕。 然而,一旦我开始使用屏幕,当我按下 phone 上的按钮时,它会给我错误 undefined is not an object (evaluating '_this2.setState'),因为我猜它无法识别“this”是什么。

我正在通过 2018 年的 Cs50 课程学习 ReactNative,其中“ScreenProps”仍然可用。我做了一些研究,我认为我的答案应该在 Initial ParamsReact ContextRedux 附近,即使我仍然不知道这些概念,但是每当我尝试查找在文档或 Youtube 上,它只是给了我比将状态从对象传递到屏幕更复杂的东西。所以这就是为什么我最终决定在这里问这个问题。

工作示例:Expo Snack

控制台输出:

你可以使用上下文来解决它API:

import React, { Component, createContext, useContext } from 'react';
import { StyleSheet, Text, View, Button, Alert } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
// import { Player } from './player';

const Stack = createStackNavigator();

const ParentContext = createContext();

export default class BoardGameApp extends Component {
  constructor(props) {
    super(props);
    this.state = { playerTable: [] };
  }

  addPlayer = (player) => {
    console.log('data added :', [...this.state.playerTable, player]);
    this.setState({
      playerTable: [...this.state.playerTable, player],
    });
  };

  render() {
    let numOfPlayers = 4;
    const totNumOfTerritories = 48;

    return (
      <ParentContext.Provider value={this.addPlayer}>
        <NavigationContainer>
          <Stack.Navigator initialRouteName="Home">
            <Stack.Screen name="Home" component={HomeScreen} />
          </Stack.Navigator>
        </NavigationContainer>
      </ParentContext.Provider>
    );
  }
}

function HomeScreen() {
  const addPlayer = useContext(ParentContext);
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button
        title="Add a new Player"
        onPress={() => {
          addPlayer({ playerName: 'whatever' });
        }}></Button>
    </View>
  );
}

const styles = StyleSheet.create({});

根据@satya 给出的评论,旧解决方案不是正确的方法,因此请避免使用它,但我保留它以备将来参考:

import * as React from 'react';
import { Component } from 'react';
import { StyleSheet, Text, View, Button, Alert } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
// import { Player } from './player';

const Stack = createStackNavigator();

export default class BoardGameApp extends Component {
  constructor(props) {
    super(props);
    this.state = { playerTable: [] };
  }

  addPlayer = (player) => {
    console.log('hi:', [...this.state.playerTable, player]);
    this.setState({
      playerTable: [...this.state.playerTable, player],
    });
  };

  render() {
    let numOfPlayers = 4;
    const totNumOfTerritories = 48;

    return (
      <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
          <Stack.Screen
            name="Home"
            component={() => <HomeScreen onClick={this.addPlayer} />}
          />
        </Stack.Navigator>
      </NavigationContainer>
    );
  }
}

function HomeScreen({ onClick }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button
        title="Add a new Player"
        onPress={() => {
          onClick({ playerName: 'whatever' });
        }}></Button>
    </View>
  );
}

const styles = StyleSheet.create({});