gpt4 book ai didi

javascript - react 原生导航 - child 不更新父更新

转载 作者:行者123 更新时间:2023-11-30 14:00:14 26 4
gpt4 key购买 nike

我对 react navigation official guide 中的示例进行了一些编辑, 以模拟主屏幕中 1 秒后的状态变化。

我不明白为什么当父屏幕状态改变时 DetailScreen 没有重新渲染。有什么方法可以获得这种行为?

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

class HomeScreen extends React.Component {
state = { value: 10 }
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Click"
onPress={() => {
const { value } = this.state;
this.props.navigation.navigate('Detail', { value });
setTimeout(() => {
this.setState({ value: value + 1 })
}, 1000);
}}
/>
</View>
);
}
}

class DetailScreen extends React.Component {
render() {
const { navigation } = this.props;
const value = navigation.getParam('value');
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Detail Screen</Text>
<Text>{value}</Text>
</View>
);
}
}

const RootStack = createStackNavigator(
{
Home: HomeScreen,
Detail: DetailScreen,
},
{
initialRouteName: 'Home',
}
);

const AppContainer = createAppContainer(RootStack);

export default class App extends React.Component {
render() {
return <AppContainer />;
}
}

小吃here

最佳答案

为什么您的代码不起作用:

您正在通过 value作为 Home 的导航 Prop 至 Details .与常规 Prop 不同,在 Home 中更改导航 Prop 的值不会导致导航 Prop 本身的值发生变化。所以如果Home是具有 Details 的父组件作为子组件,像这样:

class HomeScreen extends React.Component {
...
<DetailsScreen
value: this.state.value
/>
...
}

然后当 this.state.value Home 的变化, this.props.value自动更改 Details .然而,由于 HomeDetails在堆栈导航器中有兄弟关系,你不能传递 value作为常规 Prop ;从 Home 传递 Prop 的唯一方法至 Details正如您所做的那样,是作为导航参数。问题是当你通过 value正如你所做的那样:

const { value } = this.state;
this.props.navigation.navigate('Detail', { value });

更新 this.state.valueHome 不会导致this.props.navigation.getParam('value')自动更新。所以在你的代码中:

const value = navigation.getParam('value');
<Text>{value}</Text>

value保持最初通过时的状态。

解决方案

有几种可能的解决方法,例如在 setTimeout 之后手动强制重新渲染或重新构建组件层次结构以创建 Home Details 的父级.但是,我认为在保留应用程序结构的同时解决问题的最佳方法如下:

而不是持有 this.state.valueHome , 把它放在 App .这遵循一般原则,即子级更新父级的状态变量(反之亦然)比组件更新其兄弟级的状态变量更容易。

更新至 App组件

App是一个 AppContainer ,您需要将 this.state.value 传递给 Details通过屏幕 Prop 。当您创建任何类型的导航器时,screenprops 是将变量传递给导航器中所有组件的方式。所以你的 App组件现在看起来像这样:

export default class App extends React.Component {

state = {value: 10} // state in App now instead of Home

updateValue = (value) => { // method to update App's state, passed to children
this.setState({value})
}

render() {
return <AppContainer screenProps={{
parentState: this.state,
updateValue: this.updateValue
}}/>;
}

}

更新至 Home组件

您唯一需要更改的是 Home组件将是 onPress功能。首先,你不会通过 value不再作为导航 Prop ,因为您将访问作为从 App 传递的 screenProps 的值到所有屏幕,而不是作为从 Home 传递的导航 Prop 至 Details .其次,而不是更新this.stateHome你会调用this.props.screenProps.updateValue()更新 App 中的状态.所以 onPress在你的Home组件现在看起来像这样:

onPress={() => {
this.props.navigation.navigate('Detail'); // no navigation prop
setTimeout(() => {
screenProps.updateValue(screenProps.appState.value + 1) // updating state of App rather than state of Home
}, 1000);
}}

更新至 Details组件

唯一的变化是Details是不是显示 this.props.navigation.getParam('value') ,您将显示 this.props.screenProps.appState.value因为我们现在得到 value来自 App 的屏幕 Prop 而不是作为 Home 的导航 Prop .所以你的 Details组件现在看起来像这样:

class DetailScreen extends React.Component {
render() {
const { screenProps } = this.props;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Detail Screen</Text>
<Text>{screenProps.appState.value}</Text>
</View>
);
}
}

全新代码

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

class HomeScreen extends React.Component {
state = { value: 10 }
render() {
const { screenProps } = this.props;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Click"
onPress={() => {
this.props.navigation.navigate('Detail'); // no navigation prop
setTimeout(() => {
screenProps.updateValue(screenProps.appState.value + 1) // updating state of App rather than state of Home
}, 1000);
}}
/>
</View>
);
}
}

class DetailScreen extends React.Component {
render() {
const { screenProps } = this.props;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Detail Screen</Text>
<Text>{screenProps.appState.value}</Text>
</View>
);
}
}

const RootStack = createStackNavigator(
{
Home: HomeScreen,
Detail: DetailScreen,
},
{
initialRouteName: 'Home',
}
);

const AppContainer = createAppContainer(RootStack);

export default class App extends React.Component {

state = {value: 10} // state in App now instead of Home

updateValue = (value) => { // method to update App's state, passed to children
this.setState({value})
}

render() {
return <AppContainer screenProps={{
appState: this.state,
updateValue: this.updateValue
}}/>;
}

}

关于javascript - react 原生导航 - child 不更新父更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56430367/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com