Matt Laszcz
Matt Laszcz

Reputation: 409

React Native Functional Component Cannot Fetch Data from the Redux store

I have a react native functional component and I am using

store.subscribe --> store.getState().id

to reach out to my redux store to retrieve the "id" stored in my redux store.

When I console.log the id value after fetching it from the redux store I am not returning any data.

Am I reaching out to the store correctly in my useEffect function in my component?

Function Component AddTask.js

function AddTask ()  {

    const [id, setId] = useState('');

    useEffect(() => {

         store.subscribe(() => { 
            
            setId(store.getState().id)
            console.log(store.getState().id);
        });
        
    });

  return (
         
         ...       
               
    );
}

Redux Store Reducer

(id will not be an empty string it is set to a value before fetching the data)

const initialState = { id: ''}

const counterReducer = (state = initialState,
   
    action) => {

  if (action.type === 'id') {
    console.log('Store'+ action.payload);
    return {
     
      id: action.payload,
    };
  }
  
  return state;
};

const store = createStore(counterReducer);

export default store;

Upvotes: 1

Views: 377

Answers (1)

HMR
HMR

Reputation: 39290

The hooks useSelector and useDispatch are part of react-redux as well as the old way to connect to redux store with connect.

You are using store directly in your component, this is not advisable since you now tightly coupled every component to a specific store implementation but regardless of a bad design decision the code should still work but you forgot to unsubscribe in the effect cleanup function and provided no dependencies so it runs every render. You probably are not doing something in code you didn't add to the question like what is dispatching the action and what do the redux devtools tell you?

Here is your code working:

const { createStore, applyMiddleware, compose } = Redux;

const initialState = {
  id: 'initial id',
};
//action types
//using constants instead of strings for action type
const ID = 'ID';
//action creators
const setIdAction = (id) => ({ type: ID, payload: id });
const reducer = (state, action) => {
  if (action.type === ID) {
    return {
      id: action.payload,
    };
  }
  return state;
};
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(
      () => (next) => (action) => next(action)
    )
  )
);
function App() {
  //you did not set initial value correctly and assuming it
  //  was an empty string
  const [id, setId] = React.useState(store.getState().id);
  React.useEffect(() => {
    store.subscribe(() => {
      setId(store.getState().id);
    });
  }, []);
  return (
    <div>
      id is: {id}
      <button
        onClick={() =>
          store.dispatch(setIdAction('From button'))
        }
      >
        set id
      </button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>

<div id="root"></div>

When your code is not working I would advice you provide a minimal working example demonstrating the problem either by sandbox or snippet

The following is how you would use react-redux to connect the components to redux:

//Adding react-redux dependencies
const { Provider, useSelector, useDispatch } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;

const initialState = {
  id: 'initial id',
};
//action types
//using constants instead of strings for action type
const ID = 'ID';
//action creators
const setIdAction = (id) => ({ type: ID, payload: id });
const reducer = (state, action) => {
  if (action.type === ID) {
    return {
      id: action.payload,
    };
  }
  return state;
};
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(
      () => (next) => (action) => next(action)
    )
  )
);
function App() {
  //no local state or effect needed
  const id = useSelector((state) => state.id);
  const dispatch = useDispatch();
  return (
    <div>
      id is: {id}
      <button
        onClick={() =>
          //no dependencies on store
          dispatch(setIdAction('From button'))
        }
      >
        set id
      </button>
    </div>
  );
}

ReactDOM.render(
  //add react-redux provider
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>


<div id="root"></div>

Upvotes: 1

Related Questions