React Native中的上下文API

时间:2018-10-10 07:24:10

标签: reactjs react-native react-native-android react-native-ios

大家好,我刚刚开始学习React本机上下文api,我想知道如何像全局状态一样全局实现 并且导航到另一个屏幕后它也不起作用,为什么我们可以在提供者<ProfileScreen screen= {this.state.contextData}/>中包含类名,我们可以在全球范围内使用它。 这是我的代码

global.cart=1
const Context = React.createContext(global.cart)

class HomeScreen extends Component<Props> {
    constructor(props){
      super(props);
      this.state={
            contextData:5
           }
      }

      Incrementhome=()=>{

        this.setState({contextData:global.cart})
          global.cart++
      }
      Decrementhome=()=>{
        this.setState({contextData:global.cart})
        global.cart--
      }
  render() {
    return (
      <View>
      <Context.Provider value={this.state.contextData}>
        <Button title="Incrementhome"
          onPress={this.Incrementhome}/>
          <Button title="decrementhome"
            onPress={this.Decrementhome}/>

<ProfileScreen screen= {this.state.contextData}/>
      </Context.Provider>
<Button title='sd' onPress={()=>{this.props.navigation.navigate('Profile')}}/>

      </View>
    )
  }
}

班级个人资料屏幕可以显示我的数据

class ProfileScreen extends Component<Props> {
  render() {
  return (
      <View style={{}}>
        <Context.Consumer>
          {data=>  <Text style={{fontSize:50}}>{data}</Text>}
        </Context.Consumer>
      </View>
    );
  }
}

也是提供者的课程资料屏幕

class ProfileScreens extends Component<Props> {
    static navigationOptions =
  {
     title: 'MainActivity',  header: <Button title='sd' onPress={()=>{this.props.navigation.navigate('ProfileScreen')}}/>
   };
  constructor(props){
    super(props);

    this.state={contextData:0
        }

    }

  render() {
    return (
      <View >
        <Context.Provider value={this.state.contextData}>
          <Button title="decrement" onPress={()=>{ this.props.changeHomeScreen() }}/>
          <Button title='sd' onPress={()=>{this.props.navigation.navigate(Profile)}}/>
        </Context.Provider>
      </View>
    );
  }
}

我的导航器

export default HomeScreen = createStackNavigator({
  HomeScreen:{
    screen:HomeScreen
  },
    Profile:{
      screen:ProfileScreen
    },
      ProfileScreens:{
        screen:ProfileScreens
      },
})

1 个答案:

答案 0 :(得分:2)

对不起,但是您对React Context API的实现不够好。阅读此https://medium.com/@mcssym/react-context-api-why-you-dont-surely-need-redux-co-e6d96ca8abca?source=linkShare-1d75ea07b723-1539164899

如果您使用contextData,则通过screen道具传递Context.Consumer的方式是没有用的。

navigation.navigate字符串而不是反应组件作为参数。

我真的不知道如何轻松地向您解释,因此我将用您必须完成的工作来重写代码。

您的导航器(某处/navigation.js)

export default Home = createStackNavigator({
    HomeScreen:{
        screen: HomeScreen
    },
    Profile:{
        screen: ProfileScreen
    },
    ProfileScreens:{
        screen: ProfileScreens // Don't need to be a Provider
    },
})

您的ProfileScreens不需要成为提供者,因为您不将其用作包装器。但是可以成为使用者,因为您使用contextData。我想它与您的“主屏幕”中的一样,也是您想使其全局的。

//IMPORTANT
import { withHomeContext } from './somewhere/contexts/home';

class ProfileScreens extends Component<Props> {
    static navigationOptions = {
               title: 'MainActivity',  
               header: <Button title='sd' onPress={()=> this.props.navigation.navigate('ProfileScreen')}/>
           };
    constructor(props){
        super(props);

        this.state = {
            contextData: props.homeProvider.contextData // Get from global context home provider
        };
    }

    decrementHome = () => {
        // Calling decrement from homeProvider
        if(this.props.homeProvider) this.props.homeProvider.decrement();
    }

    render() {
        return (
            <View >
                {/*You must call the decrementHome from your provider*/}
                <Button title="decrement" onPress={this.decrementHome}/>
                <Button title='sd' onPress={()=> this.props.navigation.navigate('ProfileScreen') }/>
            </View>
        );
    }
}

export default withHomeContext(ProfileScreens);

您的ProfileScreen。您必须更改将其创建为使用者的方式。使用在withHomeContext类中创建的函数HomeContext更好。

//IMPORTANT
import { withHomeContext } from './somewhere/contexts/home';

class ProfileScreen extends Component<Props> {
    render() {
        return (
            <View style={{}}>
                <Text style={{fontSize:50}}>{this.props.homeProvider.contextData}</Text>
            </View>
        );
    }
}

export default withHomeContext(ProfileScreen);

最后,您与提供者和消费者之间的HomeContext可能是:

// In Your context/home.js

const HomeContext = React.createContext();


export class HomeProvider extends React.Component {

    state = {
        contextData: 5 //Default Value
    };


    decrementHome = () => {
        this.setState(prevState => {
            contextData: prevState.contextData - 1;
        });
    }

    incrementHome = () => {
        this.setState(prevState => {
            contextData: prevState.contextData + 1;
        });
    }

    getValues = () => {
        return {
            contextData: this.state.contextData,
            decrement: this.decrementHome, // Call via homeProvider prop
            increment: this.incrementHome // Call via homeProvider prop
        }
    }

    render() {
        return (
            <HomeContext.Provider value={this.getValues()}>
                {this.props.children}
            </HomeContext.Provider>
        );
    }
}

export function withHomeContext(Component) {
    class ComponentWithContext extends React.Component {
        render {
            return (
                <HomeContext.Consumer>
                    {(value) => <Component {...this.props} homeProvider={value} />
                </HomeContext.Consumer>
            );
        };
    }

    return ComponentWithContext;
}

立即在您的根应用程序中

import { HomeProvider } from './somwhere/context/home';
import Home from './somwhere/navigation';

export default class App extends React.Component {

    render() {
        return (
            <HomeProvider>
                <Home />
            </HomeProvider>
        );
    }

}