如何传递多个值以响应本机上下文 API

Posted

技术标签:

【中文标题】如何传递多个值以响应本机上下文 API【英文标题】:How to pass multiple values to react native context API 【发布时间】:2021-03-28 05:39:14 【问题描述】:

我是反应原生概念的新手。我正在尝试将函数和参数传递给上下文 API,以便我可以在我的子组件中访问它们。我正在尝试实现基本的登录功能,该功能将根据用户登录状态显示不同的消息。当我将 SignIn 方法传递给我的子组件时,该功能起作用,但是当我将它与一些变量一起发送时,无法访问相同的函数。下面的代码和注释可以清楚地说明问题。

在下面的代码中,你可以看到我正在传递我的减速器函数和初始状态,从中我得到错误消息和签名函数<AuthenticationContext.Provider value=[authContext, initialLoginState]>

App.js

import * as React from 'react';
import  NavigationContainer  from '@react-navigation/native';
import BottomNavigation from './src/Navigations/BottomNavigation';
import AuthStackNavigation from './src/Navigations/AuthStackNavigation'
import  useEffect, useMemo, useReducer  from 'react';
import  View  from 'react-native-animatable';
import apiCaller from "./src/api/apiCaller";
import  ActivityIndicator, Text  from 'react-native';
import  AuthenticationContext  from './src/context/AuthenticationContext'
import  Provider as VideoProvider  from './src/context/videoContext'
import  Context as VideoContext  from './src/context/videoContext'
import AsyncStorage from '@react-native-async-storage/async-storage'

export default function App() 

  //Initial state values
  const initialLoginState = 
    isLoading: true,
    userName: null,
    userToken: null,
    errorMessage: ''
  

  //Reducer function
  const loginReducer = (prevState, action) => 
    switch (action.type) 
      case 'LOGIN':
        return 
          ...prevState,
          userToken: action.token,
          userName: action.id,
          isLoading: false
        ;
      case 'LOGOUT':
        return 
          ...prevState,
          userName: null,
          userToken: null,
          isLoading: false,
        ;
      case 'REGISTER':
        return 
          ...prevState,
          userToken: action.token,
          userName: action.id,
          isLoading: false,
        ;
      case 'ERROR':
        return 
          ...prevState,
          errorMessage: action.response,
          isLoading: false
        ;
      default:
        return  userToken: null 
    
  

  //Defining useReducer
  const [newLoginState, dispatch] = useReducer(loginReducer, initialLoginState);

  const authContext = useMemo(() => (
    signIn: async (email, password) => 
      try 
        const userData = 
          email: email,
          password: password,

        ;
        const response = await apiCaller.post("/login", userData);
        if (response.data.code == '200') 
          await AsyncStorage.setItem('userToken', response.data.token)
          dispatch( type: 'LOGIN', id: email, token: response.data.token )
        
        else if (response.data.code == '404') 
          dispatch( type: 'ERROR', response: response.data.message )
        
       catch (err) 
        console.log(err);
      
    
  ), []);


  return (
    <VideoProvider value=VideoContext>
      <AuthenticationContext.Provider value=authContext, initialLoginState>
        <NavigationContainer>
          newLoginState.userToken == null ?
            <AuthStackNavigation />
            :
            <BottomNavigation />
          
        </NavigationContainer>
      </AuthenticationContext.Provider>
    </VideoProvider>
  );

在下面的文件中,我通过

获取提供者值

const signIn, initialLoginState = useContext(AuthenticationContext) 但它给了我“signIn 不是函数。(在 'signIn(email, password)' 中,'signIn' 未定义)”错误,但 signIn 方法可在以下情况下访问我只是尝试单独传递和访问 SignIn 方法。

Signinscreen.js

import React,  useState  from 'react'
import  Ionicons, MaterialIcons  from '@expo/vector-icons';
import  Text, View, StyleSheet, TouchableOpacity, Platform, StatusBar  from 'react-native';
import  WindowHeight, WindowWidth  from '../utils/PlatformDimention'
import PrimaryFormInput from "../components/PrimaryFormInput";
import PrimaryFormButton from "../components/PrimaryFormButton";

import  AuthenticationContext  from "../context/AuthenticationContext";
import  useContext  from 'react';

const UserLogin = ( navigation ) => 

    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const  signIn, initialLoginState  = useContext(AuthenticationContext)

    const loginHandle = (email, password) => 
        signIn(email, password);
    

    return (
        <View style=styles.container>
            <StatusBar barStyle='light-content' />
            <View style=styles.header>
                <View style= flex: 1, >
                    <TouchableOpacity onPress=() => navigation.goBack()>
                        <MaterialIcons style=styles.goBack name="arrow-back" size=WindowHeight / 27 />
                    </TouchableOpacity>
                </View>
                <View style= flex: 2, alignItems: 'center', justifyContent: 'center', >
                    <Ionicons
                        style= color: "#fff"  name="logo-bitbucket" size=WindowHeight * 10 / 100 />
                </View>
                <View style= flex: 1, alignItems: 'flex-end' >

                </View>
            </View>
            <View style=styles.footer>
                <View style=styles.topFlex></View>
                <View style=styles.middleFlex>
                    <Text style=styles.loginText>Welcome!</Text>
                    <Text style=styles.loginSubTextSub>Login to your existing account.</Text>
                    <PrimaryFormInput
                        inputValue=email
                        onChangeText=(userEmail) => setEmail(userEmail)
                        inputPlaceHolder='Email'
                        iconName="user"
                        keyboardType="email-address"
                        autoCapitalize="none"
                        autoCorrect=false
                    />
                    <PrimaryFormInput
                        inputValue=password
                        onChangeText=(userPassword) => setPassword(userPassword)
                        inputPlaceHolder='Password'
                        iconName="key"
                        secureTextEntry=true
                    />
                    <PrimaryFormButton
                        ButtonText='Login'
                        onPress=() => loginHandle(email, password)
                    />
                </View>
                <View style=styles.bottomFlex></View>
            </View>
        </View>
    )


export default UserLogin

谁能告诉我如何将方法和参数都传递给我的子组件并访问它?

【问题讨论】:

【参考方案1】:

你的错误就在这里

const  signIn, initialLoginState  = useContext(AuthenticationContext)

因为你像这样传递上下文对象

<AuthenticationContext.Provider value=authContext, initialLoginState>

你需要像这样进行解构

const  authContext :  signIn , initialLoginState  = useContext(AuthenticationContext)

【讨论】:

非常感谢您的快速回复。破坏后我能够轻松地传递参数,但即使我通过 reducer 函数更新 errorMessage 参数,它在我的 Singin 屏幕上也显示为空。知道可能是什么原因吗? 请忽略我上面的评论。我能够从减速器获得最新值。

以上是关于如何传递多个值以响应本机上下文 API的主要内容,如果未能解决你的问题,请参考以下文章

通过本机反应传递复选框值以显示/隐藏密码

如何在 Azure API 管理策略中重用响应上下文变量?

useContext 给出未定义的

Gatsby:如何将多个上下文 ID 传递给单个查询?

如何在 Context API 中传递路由参数

链接多个上下文提供程序在反应本机的同一领域工作