React Native 如何将应用程序的当前状态传递到选项卡导航屏幕

s4n0splo  于 2022-12-19  发布在  React
关注(0)|答案(3)|浏览(160)

如果我使用的是React Navigation v5,那么通过Tab和Stack导航器将父组件(在我的例子中是主应用程序)的当前状态向下传递到我希望在其中使用当前状态的屏幕的最佳方式是什么?
根据文档,我为每个包含相应屏幕的选项卡创建了一个堆栈导航器。
App.js包含一个状态,需要用于一些事情,最重要的是,它将在Tab导航器上提供徽章计数,以及在其中一个Tab屏幕上作为Flatlist数据的来源。
在标签页导航器的堆栈导航器中,从App一直向下到子组件获取状态的正确方法是什么?

应用程序js

const Tab = createBottomTabNavigator()

export default class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      neededArray: []
    }
  }

  const updateTheArray = (newArray) => {
    this.setState({
      neededArray: newArray
    })
  }

  componentDidMount(){
    //Listener that searches for nearby bluetooth beacons and updates the array with the passed function
    startObserver(updateTheArray)
  }

  componentWillUnmount(){
    stopObserver()
  }

  render(){
    return(
      <NavigationContainer>
        <Tab.Navigator>
          <Tab.Screen
            name = "Home"
            component = { HomeStack }/>
          <Tab.Screen
            name = "About"
            component = { AboutStack }/>

          //The Stack that contains the screen that I need to use the App's state in
          <Tab.Screen
            name = "Nearby"
            component = { NearbyStack }/>
        </Tab.Navigator>
      </NavigationContainer>
    )
  }
}

邻近堆栈. js

//This stack holds the screen that I need to use the App's state in

const NearbyStackNav = createStackNav()

const NearbyStack = () => {
  return(
    <NearbyStackNav.Navigator>
      <NearbyStackNav.Screen
        name = "Nearby"
        component = { NearbyScreen }
      />
    </NearbyStackNav.Navigator>
  )
}

附近屏幕. js

//The screen that I want to use the App's state in
const NearbyScreen = () => {
  return(
    <View>
      <FlatList
        //Where I would like to use the App's state
      />
    </View>
  )
}
dohp0rv5

dohp0rv51#

您可以向屏幕传递一些初始参数。如果您在导航到此屏幕时没有指定任何参数,则将使用初始参数。它们也会与您传递的任何参数浅合并。初始参数可以使用initialParams属性指定:

用法

<Tab.Screen
            name = "Nearby"
            component = { NearbyStack }
            initialParams={{ arrayItem: this.state.neededArray }}
 />

附近屏幕.js

React.useEffect(() => {
    if (route.params?.arrayItem) {
      // Post updated, do something with `route.params.arrayItem`
      // For example, send the arrayItem to the server
    }
  }, [route.params?.arrayItem]);
a0zr77ik

a0zr77ik2#

我的解决方案是使用React的Context API。

信标上下文. js- * 新建 *

import React from 'react'

const BeaconContext = React.createContext()

export default BeaconContext

App.js - * 已修改 *

import BeaconContext from './path/to/BeaconContext'

const Tab = createBottomTabNavigator()

export default class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      neededArray: []
    }
  }

  const updateTheArray = (newArray) => {
    this.setState({
      neededArray: newArray
    })
  }

  componentDidMount(){
    startObserver(updateTheArray)
  }

  componentWillUnmount(){
    stopObserver()
  }

  render(){
    return(
      // Wrap the nav container in the newly created context!!!

      <BeaconContext.Provider value = { this.state.neededArray }
        <NavigationContainer>
          <Tab.Navigator>
            <Tab.Screen
              name = "Home"
              component = { HomeStack }/>
            <Tab.Screen
              name = "About"
              component = { AboutStack }/>
            <Tab.Screen
              name = "Nearby"
              component = { NearbyStack }/>
          </Tab.Navigator>
        </NavigationContainer>
      </BeaconContext.Provider>
    )
  }
}

邻近堆栈. js- * 未更改 *

const NearbyStackNav = createStackNav()

const NearbyStack = () => {
  return(
    <NearbyStackNav.Navigator>
      <NearbyStackNav.Screen
        name = "Nearby"
        component = { NearbyScreen }
      />
    </NearbyStackNav.Navigator>
  )
}

NearbyScreen.js - * 已修改 *

import BeaconContext from './path/to/BeaconContext'

const NearbyScreen = () => {
  return(
    <View>
      //Wrap the component in the new context's consumer!!!

      <BeaconContext.Consumer>
      {
        context => <Text>{ context }</Text>
      }
      </BeaconContext.Consumer>
    </View>
  )
}
33qvvth1

33qvvth13#

我一直在纠结于同样的问题--当使用initialProps属性向Tab.Screen传递一个状态时,屏幕从来没有接收到任何更新。它读取了一次初始状态值,然后什么都没有。
为了让它工作,我跳过了使用initialProps属性,而是使用Tab上的children属性。屏幕如下:

应用程序包含<Tab.Navigator>和<Tab.Screen>:

const[myBool, setMyBool] = useState(false)

<Tab.Screen
   name="MyTab"
   children={() => (
     <MySecondScreen passedStateParam={ myBool } />
   )}
   .
   .
   .
</Tab.Screen>

MySecondScreen正在消耗已传递myBool状态的更新:

export function MySecondScreen ({ passedStateParam }) {
    const myPassedBoolState = passedStateParam
    React.useEffect(() => {
        if(myPassedBoolState) {
             //Act upon App.tsx updating the state
        }
    }, [myPassedBoolState])
}

不确定在尝试使用initialParams属性执行此操作时是否遗漏了一些内容,但通过这种方式(使用children属性),我至少让它工作了。

相关问题