新的上下文api应该如何与React Native导航器一起使用?

时间:2018-07-05 09:16:23

标签: reactjs react-native react-navigation react-context

我按照以下示例使用React Navigator创建了一个多屏应用程序:

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

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

export default App;

现在,我想使用the new builtin context api添加全局配置状态,这样我可以拥有一些可以在多个屏幕上进行操作和显示的通用数据。

问题是上下文显然需要具有公共父组件的组件,以便可以将上下文传递给子组件。

我如何使用我所知的不共享公共父屏幕的屏幕来实现此目的,因为它们是由react导航器管理的?

4 个答案:

答案 0 :(得分:12)

您可以这样做。

创建新文件: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>
);

index.js上,将根组件与上下文提供者组件一起包装。

<GlobalContextProvider>
  <App />
</GlobalContextProvider>

然后在屏幕上HomeScreen.js使用这样的使用者组件。

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);

您还可以创建多个上下文提供程序来分离您的关注点,并在所需的屏幕上使用HOC使用者。

答案 1 :(得分:1)

此答案包含考虑因素react-navigation程序包。

您必须用App包装ContextProvider组件,才能在两个屏幕上访问上下文。

    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>);
    }

答案 2 :(得分:0)

如果您想了解详细的教程,可以点击以下链接: 访问:https://www.thelearninguy.com/simple-react-native-context-api-detailed

很长的答案如下。

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;

礼貌-https://www.thelearninguy.com

答案 3 :(得分:0)

https://wix.github.io/react-native-navigation/docs/third-party-react-context/

由于RNN屏幕不是同一组件树的一部分,因此在共享上下文中更新值不会触发所有屏幕的重新渲染。但是,您仍然可以按每个RNN屏幕组件树使用React.Context。

如果您需要在所有屏幕上触发重新渲染,则有许多流行的第三方库,例如MobX或Redux。