How should the new context api work with React Native navigator?

陌路散爱 提交于 2019-12-03 04:27:19

问题


I created a multiscreen app using React Navigator following this example:

import {
  createStackNavigator,
} from 'react-navigation';

const App = createStackNavigator({
  Home: { screen: HomeScreen },
  Profile: { screen: ProfileScreen },
});

export default App;

Now I'd like to add a global configuration state using the new builtin context api, so I can have some common data which can be manipulated and displayed from multiple screens.

The problem is context apparently requires components having a common parent component, so that context can be passed down to child components.

How can I implement this using screens which do not share a common parent as far as I know, because they are managed by react navigator?


回答1:


You can make it like this.

Create new file: GlobalContext.js

import React from 'react';

const GlobalContext = React.createContext({});

export class GlobalContextProvider extends React.Component {
  state = {
    isOnline: true
  }

  switchToOnline = () => {
    this.setState({ isOnline: true });
  }

  switchToOffline = () => {
    this.setState({ isOnline: false });
  }

  render () {
    return (
      <GlobalContext.Provider
        value={{
          ...this.state,
          switchToOnline: this.switchToOnline,
          switchToOffline: this.switchToOffline
        }}
      >
        {this.props.children}
      </GlobalContext.Provider>
    )
  }
}

// create the consumer as higher order component
export const withGlobalContext = ChildComponent => props => (
  <GlobalContext.Consumer>
    {
      context => <ChildComponent {...props} global={context}  />
    }
  </GlobalContext.Consumer>
);

On index.js wrap your root component with context provider component.

<GlobalContextProvider>
  <App />
</GlobalContextProvider>

Then on your screen HomeScreen.js use the consumer component like this.

import React from 'react';
import { View, Text } from 'react-native';
import { withGlobalContext } from './GlobalContext';

class HomeScreen extends React.Component {
  render () {
    return (
      <View>
        <Text>Is online: {this.props.global.isOnline}</Text>
      </View>
    )
  }
}

export default withGlobalContext(HomeScreen);

You can also create multiple context provider to separate your concerns, and use the HOC consumer on the screen you want.




回答2:


This answers takes in consideraction react-navigation package.

You have to wrap your App component with the ContextProvider in order to have access to your context on both screens.

    import { createAppContainer } from 'react-navigation'
    import { createStackNavigator } from 'react-navigation-stack'
    import ProfileContextProvider from '../some/path/ProfileContextProvider'

    const RootStack = createStackNavigator({
      Home: { screen: HomeScreen },
      Profile: { screen: ProfileScreen },
    });

    const AppContainer = createAppContainer(RootStack)    
    const App = () => {
      return (
      <ProfileContextProvider>
        <AppContainer />
      </UserContextProvider>);
    }



回答3:


If you want the detailed tutorial you could follow the below link : Visit : https://www.thelearninguy.com/simple-react-native-context-api-detailed

A very long answer would be as follows.

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

//make a new context
const MyContext = React.createContext();

//create provider component
class MyProvider extends Component {
    state = {
        name: "The Learnin Guy",
        age: 50
    };
    increaseAge = () => {
        this.setState({
            age: this.state.age + 1
        });
    };

    render() {
        return (
            <MyContext.Provider
                value={{
                    state: this.state,
                    increaseAge: this.increaseAge
                }}
            >
                {this.props.children}
            </MyContext.Provider>
        );
    }
}

class Person extends Component {
    render() {
        return (
            <View>
                <Text>This is Person Component</Text>
                <MyContext.Consumer>
                    {(context) => (
                        <React.Fragment>
                            <Text>Name: {context.state.age}</Text>
                            <Text>Age: {context.state.age}</Text>
                            <Button title="IncreaseAge" onPress={context.increaseAge} />
                        </React.Fragment>
                    )}
                </MyContext.Consumer>
            </View>
        );
    }
}

class Family extends Component {
    render() {
        return (
            <View>
                <Text>This is Family Component</Text>
                <MyContext.Consumer>
                    {(context) => (
                        <React.Fragment>
                            <Text>Age: {context.state.age}</Text>
                        </React.Fragment>
                    )}
                </MyContext.Consumer>
                <Person/>
            </View>
        );
    }
}

class App extends Component {
    render() {
        return (
            <MyProvider>
                <View>
                    <Text>This is App Component</Text>
                    <MyContext.Consumer>
                        {(context) => (
                            <React.Fragment>
                                <Text>Age: {context.state.age}</Text>
                            </React.Fragment>
                        )}
                    </MyContext.Consumer>
                    <Family/>
                </View>
            </MyProvider>
        );
    }
}

export default App;

Courtesy - https://www.thelearninguy.com



来源:https://stackoverflow.com/questions/51187582/how-should-the-new-context-api-work-with-react-native-navigator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!