Search code examples
reactjstypescriptreact-nativereduxredux-toolkit

error is coming Cannot read properties of null (reading 'store')


I am trying to pass data from redux store to other components but error is coming tried many things.

The code of app.js is as follows which is wrapped in provider

import React from 'react';
import Babe from './Babe';
import type { PropsWithChildren } from 'react';
import Test from './navigate/Test';
import Hot from './navigate/Hot';
import Coffee from './navigate/Coffee';
import Tea from './navigate/Tea';
import FullCourse from './navigate/FullCourse';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import FullCourse2 from './navigate/FullCourse2';
import { Provider } from 'react-redux';
import store from './src/app/store';
import { useSelector } from "react-redux";
import { showData } from './src/features/showslice'

const Stack = createStackNavigator();

Above sections have all the necessary imports, the below part is where the problem is in the use of useSelector hook.

const App = () => {
  const data = useSelector((c) => {
    return console.log(c)
  })

  return (
    <Provider store={store}>
      <NavigationContainer>
        <Stack.Navigator screenOptions={{ headerShown: false }}>
          <Stack.Screen name="In-Flight Services" component={Babe} />
          <Stack.Screen name="Cold Water" component={Test} />
          <Stack.Screen name="Hot Water" component={Hot} />
          <Stack.Screen name="Tea" component={Tea} />
          <Stack.Screen name="Coffee" component={Coffee} />
          <Stack.Screen name="Meal" component={FullCourse} />
          <Stack.Screen name="Meal2" component={FullCourse2} />
        </Stack.Navigator>
      </NavigationContainer>
    </Provider>
  )
}

export default App;

The slice code is as follows, I am trying to access the value of 5 that is state.value into app.js.

import { createSlice } from '@reduxjs/toolkit'

// const initialState = { value: 0 }

export const showslice = createSlice({
  name: 'showData',
  initialState: { value: 3 },
  reducers: {
    addData: () => { },
    showData: (state, action) => {
      return state.value = 5
    }
  }
})

export const { addData, showData } = showslice.actions
export default showslice.reducer

// Action creators are generated for each case reducer function
// the showData in the store which is being assigned represents showslice.reducer

The store code is as follows

// import { configureStore } from '@reduxjs/toolkit'
import { configureStore } from '@reduxjs/toolkit'
import showData from '../features/showslice'

const store = configureStore({
  reducer: {
    show: showData
  },
})

export default store

The imports are all correct checked multiple times.

I am expecting the value of useSelector to be stored in const data in order to display it, but at the line of useSelector the error is happening.


Solution

  • The App component is the component rendering the Redux store Provider component, so App itself cannot subscribe to the store via the useSelector hook. If App needs to subscribe to the store then the Provider component should be moved higher in the ReactTree than the App component trying to access the context it provides.

    Example:

    Provider provides Redux context to its sub-ReactTree.

    <Provider store={store}>
      <App />
    </Provider>
    
    const App = () => {
      const data = useSelector((state) => state.show.value); // <-- can access store
    
      return (
        <NavigationContainer>
          <Stack.Navigator screenOptions={{ headerShown: false }}>
            <Stack.Screen name="In-Flight Services" component={Babe} />
            <Stack.Screen name="Cold Water" component={Test} />
            <Stack.Screen name="Hot Water" component={Hot} />
            <Stack.Screen name="Tea" component={Tea} />
            <Stack.Screen name="Coffee" component={Coffee} />
            <Stack.Screen name="Meal" component={FullCourse} />
            <Stack.Screen name="Meal2" component={FullCourse2} />
          </Stack.Navigator>
        </NavigationContainer>
      );
    };
    

    Additionally, the slice reducers should only mutate the state or return the next state value, but not ever both.

    export const showslice = createSlice({
      name: 'showData',
      initialState: { value: 3 },
      reducers: {
        addData: () => { },
        showData: (state, action) => {
          state.value = 5;
        },
      }
    })
    

    or

    export const showslice = createSlice({
      name: 'showData',
      initialState: { value: 3 },
      reducers: {
        addData: () => { },
        showData: (state, action) => {
          return { value: 5 };
        },
      }
    })