Search code examples
react-nativereduxstore

React Native redux using connect and store in the same component


I'm working on a react native app, i use redux to manage global state. I want to store a state in the app component where i call the store :

/* eslint-disable global-require */
import React, { Component } from 'react'
import { Provider, connect } from 'react-redux'
import { BackHandler } from 'react-native'
// ***************************************************
import AppContainer from './eXpand/Components/Navigation';
// ***************************************************
import { AppLoading } from 'expo'
import * as Font from 'expo-font'
import { Ionicons } from '@expo/vector-icons'
import {
  cacheAssets,
  cacheFonts
} from './eXpand/Helpers/Defaults/AssetsCaching'
import store from '~/Store/store'
import registerForPushNotificationsAsync from './eXpand/Components/Services/notifications';

// Local Import
import { setUserGsm } from '~/Store/actions';

class App extends Component {
  _isMounted = false;
  constructor(props) {
    super(props)
    this.state = {
      isReady: false,
      GSM: null
    }
  }

  /**
 * Demande d'autorisation pour accéder au token du GSM et l'envoyer vers l'api
 */
  async registerForPush() {
    const { status: existingStatus } = await Permissions.getAsync(
      Permissions.NOTIFICATIONS
    );
    let finalStatus = existingStatus;
    if (existingStatus !== 'granted') {
      const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
      finalStatus = status;
    }
    if (finalStatus !== 'granted') {
      return;
    }
    let gsm = await Notifications.getExpoPushTokenAsync();

    if (this._isMounted) {
      this.setState({
        GSM: gsm
      });
    }

    console.log("### GSM TOKEN GSM ###")
    console.log(this.state.GSM)
    console.log("#####################")
  }

  /**
   * Add Font with Asynchronous Method
   */

  async componentDidMount() {
    console.log("##########  COMPONENT DID MOUNT   ############")
    this._isMounted = true;
    if (this._isMounted) {
      this.registerForPush()
      this.props.setUserGsm(this.state.GSM)
    }
    BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
    await Font.loadAsync({
      // ROBOTO
      Roboto: require('native-base/Fonts/Roboto.ttf'),
      Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
      // SFUIDisplay
      SFUIDisplayBlack: require('^/Fonts/SFUIDisplay-Black.otf'),
      SFUIDisplayBold: require('^/Fonts/SFUIDisplay-Bold.otf'),
      SFUIDisplayHeavy: require('^/Fonts/SFUIDisplay-Heavy.otf'),
      SFUIDisplayLight: require('^/Fonts/SFUIDisplay-Light.otf'),
      SFUIDisplayMedium: require('^/Fonts/SFUIDisplay-Medium.otf'),
      SFUIDisplaySemibold: require('^/Fonts/SFUIDisplay-Semibold.otf'),
      SFUIDisplayThin: require('^/Fonts/SFUIDisplay-Thin.otf'),
      SFUIDisplayUltralight: require('^/Fonts/SFUIDisplay-Ultralight.otf'),
      // MyriadPro
      MYRIADPROBOLD: require('^/Fonts/MyriadPro-Bold.otf'),
      MyriadProBlackSemiCn: require('^/Fonts/MyriadPro-BlackSemiCn.otf'),
      MyriadProBoldSemiExtended: require('^/Fonts/MyriadPro-BoldSemiExtended.ttf'),
      ...Ionicons.font,
      // PTSans
      PTSansRegular: require('^/Fonts/PTSans-Regular.ttf'),
      PTSansBold: require('^/Fonts/PTSans-Bold.ttf'),
      PTSansItalic: require('^/Fonts/PTSans-Italic.ttf'),
    })
    this.setState({ isReady: true })
  }

  componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
    console.log("##########  COMPONENT WILL MOUNT   ############")
    this._isMounted = false;
  }

  handleBackButton() {
    return true;
  }

  async _loadAssetsAsync() {
    const imageAssets = cacheAssets([require('^/Logos/expanded.png')])

    const fontAssets = cacheFonts({
      // ROBOTO
      Roboto: require('native-base/Fonts/Roboto.ttf'),
      Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
      // SFUIDisplay
      SFUIDisplayBlack: require('^/Fonts/SFUIDisplay-Black.otf'),
      SFUIDisplayBold: require('^/Fonts/SFUIDisplay-Bold.otf'),
      SFUIDisplayHeavy: require('^/Fonts/SFUIDisplay-Heavy.otf'),
      SFUIDisplayLight: require('^/Fonts/SFUIDisplay-Light.otf'),
      SFUIDisplayMedium: require('^/Fonts/SFUIDisplay-Medium.otf'),
      SFUIDisplaySemibold: require('^/Fonts/SFUIDisplay-Semibold.otf'),
      SFUIDisplayThin: require('^/Fonts/SFUIDisplay-Thin.otf'),
      SFUIDisplayUltralight: require('^/Fonts/SFUIDisplay-Ultralight.otf'),
      // MyriadPro
      MYRIADPROBOLD: require('^/Fonts/MyriadPro-Bold.otf'),
      MyriadProBlackSemiCn: require('^/Fonts/MyriadPro-BlackSemiCn.otf'),
      MyriadProBoldSemiExtended: require('^/Fonts/MyriadPro-BoldSemiExtended.ttf'),
      // PTSans
      PTSansRegular: require('^/Fonts/PTSans-Regular.ttf'),
      PTSansBold: require('^/Fonts/PTSans-Bold.ttf'),
      PTSansItalic: require('^/Fonts/PTSans-Italic.ttf'),
    })

    await Promise.all([imageAssets, fontAssets])
  }

  render() {
    const Root = () => {
      if (!this.state.isReady) {
        return (
          <AppLoading
            startAsync={this._loadAssetsAsync}
            onFinish={() => this.setState({ isReady: true })}
          />
        )
      }
      return <AppContainer />
    }

    return (
      <Provider store={store}>
        <Root />
      </Provider>
    )
  }
}
const mapStateToProps = (state) => ({
  GSM: state.GSM
});

const mapDispatchToProps = (dispatch) => ({
  setUserGsm: (GSM) => {
    dispatch(setUserGsm(GSM));
  }
});

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(App);

I get this error :

Invariant Violation: Could not find "store" in the context of "Connect(App)". Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(App) in connect options.


Solution

  • You cannot do it this way.

    The react-redux Provider is passing store to the react-redux connect. And you are using connect in component which is not wrapped (somewhere in React component tree) in Provider (the your component itself is rendering Provider, which is too late).