简体   繁体   中英

Accessing global state when using Context API

I have used context API for state management which worked successfully to access data in a component.The data being used is currency prices for Foreign Exchange Pairs. This data keeps on updating after an interval of 1000ms as its being fetched from an API. How do i access this data in another component in the same manner as i receive it in the first component. Passing the prices data as arguments in the navigation.navigate('CreateAlertScreen) does not pass the data that keeps updating. Below is the code.

//HomeScreen

import React, {useContext} from 'react'
import { Text, View, ActivityIndicator, ScrollView, TouchableOpacity } from 'react-native'
import {ListItem, Card, Button, Icon} from 'react-native-elements'
//import CurrencyPair from '../../CurrencyPair'
import {firebase} from '../../../firebase/config'
import {CurrencyContext} from '../../../context/Context'

function HomeScreen({navigation}) {

    const currency = useContext(CurrencyContext);


return (
        <ScrollView>
    
        <Card>
            <Text style={{textAlign: "center"}}>
                Welcome
            </Text>
            <Button title="Sign Out" type="outline" onPress ={() => firebase.auth().signOut()}/>
            <Button title="My Alerts"  onPress ={() =>navigation.navigate("AlertScreen") }/>
            
        </Card>
  
        <View>
            {currency.data.prices && currency.data.prices.map((prices, index) => {
                return (
      <ListItem
        key={index}
        //passing data from HomeScreen to CreateAlert Screen with  the initialized parameters
        onPress = {() => navigation.navigate('CreateAlertScreen')}
        bottomDivider>
        <ListItem.Content>
            <ListItem.Title>
            {currency.data.prices[index].instrument}        {currency.data.prices[index].closeoutAsk}        {currency.data.prices[index].closeoutBid}
            </ListItem.Title>
        </ListItem.Content>
      </ListItem>     
                )
            })
}
        </View>
       
    </ScrollView>


    
)
}
export default HomeScreen

// Context

import React, {createContext, useState, useEffect}from 'react'
import {ActivityIndicator} from 'react-native'
import axios from '../utils/axios'

const CurrencyContext = createContext();

const CurrencyProvider =(props) => {
    const [data, setData] = useState([])
    const [isLoading, setIsloading] = useState(true)

    useEffect(() => {
        const interval = setInterval(() => {
            const fetchpairs = async() => {
                const results = await axios.get('/v3/accounts/101-004-14328428-002/pricing?instruments=AUD_CAD%2CAUD_CHF%2CAUD_JPY%2CAUD_NZD%2CAUD_USD%2CCAD_CHF%2CCAD_JPY%2CCHF_JPY%2CEUR_AUD%2CEUR_CAD%2CEUR_CHF%2CEUR_GBP%2CEUR_NOK%2CEUR_NZD%2CEUR_USD%2CGBP_AUD%2CGBP_CAD%2CGBP_CHF%2CGBP_USD%2CGBP_JPY%2CNZD_CAD%2CNZD_CHF%2CNZD_JPY%2CUSD_CAD%2CUSD_JPY%2CUSD_CHF%2CUSD_ZAR%2CUSD_MXN')
                setData(results.data)
                setIsloading(false)
            }
            fetchpairs() 
        },1000)
      }, []);

      if(isLoading) {
        return (
            <ActivityIndicator size="large"/>
        )
    }else
    return (
        <CurrencyContext.Provider
        value={{
            data,
            setData,
            isLoading,
            setIsloading
        }}>
            {props.children}

        </CurrencyContext.Provider>

       
    )
}

export {CurrencyProvider, CurrencyContext}

// CreateAlertScreen

import React, {useContext,useState} from 'react'
import { View, Text,TextInput, StyleSheet, Picker, TouchableOpacity, Button, PushNotificationIOS } from 'react-native'
import {Card, CheckBox } from 'react-native-elements'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import {FoodContext} from '../../../context/Context'
import styles from './styles'

const CreateAlertScreen =()=> {

    const create = useContext(FoodContext);
// hook for the message textinput
    const [message, setMessage] = useState(null)

    return (
        <View style={styles.container}>
            
             <KeyboardAwareScrollView
                style={{ flex: 1, width: '100%' }}
                keyboardShouldPersistTaps="always">
            <Card>
                <Card.Title>
                    Pair:   {} 
                </Card.Title>
                <Card.Divider/>
                <Text style={{textAlign:"center"}}>
               BidPrice: {BidPrice} / AskPrice:{AskPrice}
                </Text>
                <Card.Divider/>
                <Text style={{textAlign: "center"}}>
                    Alert When : 
                </Text>

                <TextInput
          style={styles.textInputStyle}
          placeholder="Price"
          placeholderTextColor="#60605e"
          numeric
          keyboardType='decimal-pad'    
        />
                <Card.Divider/> 

                <TextInput
                value={message}
                onChangeText={(message) =>setMessage(message)}
                style={styles.input}
                />
                <TouchableOpacity
                style={styles.button}
                onPress={() => navigation.navigate('AlertScreen', {
                    alert: message
                })}
                >
                    <Text style={styles.buttonTitle}>CreateAlert</Text>
                </TouchableOpacity>
                

            
        </Card>
        </KeyboardAwareScrollView>
        </View>
    )
}

export default CreateAlertScreen

Your app is set up wrong from what I can tell. Create context on your Top level component and wrap your entire app render in the context provider. Then every component can have access to your context. (Provided you use useContext)

Straight from the documentation

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

As you can see the entire app is wrapped in the ThemeContext.Provider passing the themes.light object as value to the Provider. And is then accessed 2 "levels" down using useContext hook.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM