【问题标题】:How to use react hooks on react-native with react-navigation如何通过 react-navigation 在 react-native 上使用反应钩子
【发布时间】:2020-05-24 09:38:58
【问题描述】:

这是使用 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”中有一个“项目”。它是通过导航添加作为道具给出的。

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 接收“items”作为 route.params。
它使用“setItems”将自己的数据推送到其中。
添加后,导航返回 HomeScreen,其中包含新添加的项目。

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;

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

【问题讨论】:

  • 你可以简单地创建一个函数来addItems而不是传递钩子变量,会不那么复杂
  • @Guruparan Giritharan 你能在答案中写下你的代码吗?
  • 如果您要从多个屏幕访问它,建议使用以下带有上下文实现的答案

标签: javascript reactjs react-native


【解决方案1】:

您应该考虑使用 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>
  );
}

您也可以使用useReducer 钩子并制作更多类似 Redux 的内容。看看这篇文章 https://medium.com/simply/state-management-with-react-hooks-and-context-api-at-10-lines-of-code-baf6be8302c

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      • 2018-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多