如何使用 react-navigation 在 react-native 上使用 react hooks

IT技术 javascript reactjs react-native
2021-05-05 23:11:31

这是使用 react-navigation 的 App.js。它有两个屏幕,称为 HomeScreen 和 AddScreen。

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

import HomeScreen from './src/HomeScreen';
import AddScreen from './src/AddScreen';

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Add" component={AddScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

这是主屏幕。“useState”中有一个“items”。它是通过导航作为props通过添加提供的。

import * as React from 'react';
import PropTypes from 'prop-types';
import { View, Text, Button } from 'react-native';


function HomeScreen({ navigation, route }) {
  const [items, setItems] = React.useState([]);

  React.useEffect(() => {
    if (route.params?.items) {
      // Post updated, do something with `route.params.post`
      // For example, send the post to the server
      console.log('saved');
    }
  }, [route.params?.items]);

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button
        title="Create post"
        onPress={() => navigation.navigate('Add', { items, setItems })}
      />
      <View>
        {items.map((item, i) => {
          return (
            <View>
              <Text>{item.itemName}</Text>
              <Text>{item.itemPrice}</Text>
            </View>
          );
        })}
      </View>
    </View>
  );
}

HomeScreen.propTypes = {
  navigation: PropTypes.object.isRequired,
};

export default HomeScreen;

并且 AddScreen 接收“项目”作为 route.params。
它使用“setItems”将自己的数据推送到其中。
添加后,导航返回主屏幕,其中包含新项目添加的项目。

import * as React from 'react';
import PropTypes from 'prop-types';

import { View, Text, Button, TextInput } from 'react-native';

function AddScreen({ route, navigation }) {
  const { items, setItems } = route.params;
  const [itemName, setItemName] = React.useState('');
  const [itemPrice, setItemPrice] = React.useState('0');

  const addItem = () => {
    setItems([...items, { itemName, itemPrice }]);
    setItemName('');
    setItemPrice('0');
  };

  return (
    <View>
      <TextInput
        multiline
        placeholder="What's on your mind?"
        value={itemName}
        onChangeText={setItemName}
      />
      <TextInput
        multiline
        placeholder="What's on your mind?"
        value={itemPrice}
        onChangeText={setItemPrice}
      />
      <Button
        title="Done"
        onPress={() => {
          addItem();
          // Pass params back to home screen
          navigation.navigate('Home', items);
        }}
      />
    </View>
  );
}

AddScreen.propTypes = {
  navigation: PropTypes.object.isRequired,
  route: PropTypes.object.isRequired,
};

export default AddScreen;

它对我的目的很有效。
但是我不确定这种方式是否正确使用react-hooks从父级到子级提供和接收数据。
你能修改我的代码吗?

2个回答

您应该考虑使用 React Context API https://uk.reactjs.org/docs/context.html它致力于共享公共状态(items在您的情况下)。这是一个示例:您应该为项目创建一个公共上下文:ItemsState.js

import React, { useState, useContext } from 'react';

const ItemsContext = React.createContext([]);

export const ItemsProvider = ({ children }) => {
  return (
    <ItemsContext.Provider value={useState([])}>
      {children}
    </ItemsContext.Provider>
  );
}

export const useItems = () => useContext(ItemsContext);

然后像这样在 App.js 中与提供者共享屏幕之间的上下文

import {ItemsProvider} from 'ItemsState';

function App() {
  return (
   <ItemsProvider> // share the items between both screens
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Add" component={AddScreen} />
      </Stack.Navigator>
    </NavigationContainer>
   </ItemsProvider>
  );
}

然后在每个屏幕中使用项目上下文,像这样 AddScreen.js

import {useItems} from './ItemsState';

function AddScreen({ route, navigation }) {
  const [items, setItems] = useItems(); // <- using items context as global useState
  const [itemName, setItemName] = React.useState('');
  const [itemPrice, setItemPrice] = React.useState('0');

  const addItem = () => {
    setItems([...items, { itemName, itemPrice }]);
    setItemName('');
    setItemPrice('0');
  };

  return (
    <View>
      <TextInput
        multiline
        placeholder="What's on your mind?"
        value={itemName}
        onChangeText={setItemName}
      />
      <TextInput
        multiline
        placeholder="What's on your mind?"
        value={itemPrice}
        onChangeText={setItemPrice}
      />
      <Button
        title="Done"
        onPress={() => {
          addItem();
          // Pass params back to home screen
          navigation.navigate('Home', items);
        }}
      />
    </View>
  );
}

你也可以使用useReducerhook 来制作更像 Redux 的东西。查看这篇文章 https://medium.com/simply/state-management-with-react-hooks-and-context-api-at-10-lines-of-code-baf6be8302c

为了在组件之间共享数据,您可以使用 Context API 或 Redux,通过导航路由传递完整对象是一种反模式,您可以在文档中找到更多信息

https://reactnavigation.org/docs/params/#what-should-be-in-params