问题
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