1

嘿伙计们,我刚开始学习 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
      },
})
4

1 回答 1

5

抱歉,您没有很好地实现 React Context API。阅读此https://medium.com/@mcssym/react-context-api-why-you-dont-surely-need-redux-co-e6d96ca8abca?source=linkShare-1d75ea07b723-1539164899

如果您contextData使用.screenContext.Consumer

字符串而不是React 组件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。我想这与您的 HomeScreen 中的相同,并且您想要使其全球化。

//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 与您的 Provider 和 Consumer 可能是:

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

}
于 2018-10-10T09:52:14.607 回答