如何传递“this.state"React Navigation 5 中的组件到屏幕 [英] How to pass "this.state" of a Component to a Screen in React Navigation 5

查看:50
本文介绍了如何传递“this.state"React Navigation 5 中的组件到屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我正在开发的应用旨在在您玩棋盘游戏时跟踪玩家和积分.这是App.js的代码:

import * as React from 'react';从反应"导入{组件};import { StyleSheet, Text, View, Button, Alert } from 'react-native';从'@react-navigation/native' 导入 { NavigationContainer };import { create StackNavigator } from '@react-navigation/stack';从'./player'导入{播放器};const Stack = createStackNavigator();导出默认类 BoardGameApp 扩展组件{构造函数(道具){超级(道具);this.state={ playerTable:[] }}使成为(){让 numOfPlayers = 4const totNumOfTerritories = 48返回 (<导航容器><Stack.Navigator initialRouteName="Home"><Stack.Screen name="Home";组件={HomeScreen}/></Stack.Navigator></NavigationContainer>);}}功能主屏幕(){返回(<视图样式={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Button title="添加新玩家";onPress={() =>this.setState({ 玩家表: [...this.state.playerTable,{玩家姓名:随便"},]})}></按钮>/* 这是注释{this.state.playerTable.map(功能(播放器){return <玩家领土={totNumOfTerritories/numOfPlayers}/>;})} 评论到此结束 */</查看>);}

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

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

解决方案

工作示例:

您可以使用 Context API 解决它:

import React, { Component, createContext, useContext } from 'react';import { StyleSheet, Text, View, Button, Alert } from 'react-native';从'@react-navigation/native' 导入 { NavigationContainer };从'@react-navigation/stack' 导入 { createStackNavigator };//从 './player' 导入 { Player };const Stack = createStackNavigator();const ParentContext = createContext();导出默认类 BoardGameApp 扩展组件 {构造函数(道具){超级(道具);this.state = { playerTable: [] };}addPlayer = (玩家) =>{console.log('数据添加:', [...this.state.playerTable, player]);this.setState({playerTable: [...this.state.playerTable, player],});};使成为() {让 numOfPlayers = 4;const totNumOfTerritories = 48;返回 (<ParentContext.Provider value={this.addPlayer}><导航容器><Stack.Navigator initialRouteName="Home"><Stack.Screen name="Home";组件={HomeScreen}/></Stack.Navigator></NavigationContainer></ParentContext.Provider>);}}功能主屏幕(){const addPlayer = useContext(ParentContext);返回 (<视图样式={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><按钮title="添加新玩家";onPress={() =>{addPlayer({ playerName: 'whatever' });}}></按钮></查看>);}const 样式 = StyleSheet.create({});

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

import * as React from 'react';从反应"导入{组件};import { StyleSheet, Text, View, Button, Alert } from 'react-native';从'@react-navigation/native' 导入 { NavigationContainer };从'@react-navigation/stack' 导入 { createStackNavigator };//从 './player' 导入 { Player };const Stack = createStackNavigator();导出默认类 BoardGameApp 扩展组件 {构造函数(道具){超级(道具);this.state = { playerTable: [] };}addPlayer = (玩家) =>{console.log('hi:', [...this.state.playerTable, player]);this.setState({playerTable: [...this.state.playerTable, player],});};使成为() {让 numOfPlayers = 4;const totNumOfTerritories = 48;返回 (<导航容器><Stack.Navigator initialRouteName="Home"><堆栈屏幕名称=家"组件={() =><HomeScreen onClick={this.addPlayer}/>}/></Stack.Navigator></NavigationContainer>);}}功能主屏幕({ onClick }){返回 (<视图样式={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><按钮title="添加新玩家";onPress={() =>{onClick({ playerName: 'whatever' });}}></按钮></查看>);}const 样式 = StyleSheet.create({});

I am new to React Native and I just started learning ReactNavigation.

The app that I'm working at is meant to keep track of players and points while you're playing a board game. Here's the code of 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>
  );
}
 

So basically what should happen is that whenever I press the Button, an object consisting of {playerName: "whatever"} should be added to the PlayerTable[] array present in the state of BoardGameApp, and then what I subsequently do is that I map over this array and render a Player component for each object {playerName: "whatever"} present in the array. When all of this was happening inside the App component without using screens everything was fine, but of course it looked awful. Once I started using screens however, when I press the Button on my phone it gives me the error undefined is not an object (evaluating '_this2.setState') because I guess it doesn't recognize what "this" is.

I am learning ReactNative by following the Cs50 course 2018 where "ScreenProps" were still available. I made some research and I think that my answer should be somewhere around Initial Params, React Contextor Redux even if I still don't know these concepts, however whenever I try to look up on the docs or on Youtube, it just gives me way more complicated stuff than just passing a state from an object to a screen. So this is why I ultimately decided to ask this question here.

解决方案

Working Example: Expo Snack

Console Output:

You can solve it using Context 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({});

Old solution which was not the right way according to comment given by @satya so avoid it but I am keeping it in answer for future ref:

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({});

这篇关于如何传递“this.state"React Navigation 5 中的组件到屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆