question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Error when I'm trying to dispatch an action outside of my React Component, the state isn't updating

See original GitHub issue

Hi, I’m trying to dispatch an action from outside React’s logic.

This app is running with Electron.

Context of the problem: In this app I’m receiving push notifications through a third-party-service (Pushy), so we need to dispatch an action which set the new state en our reducer , so we can handle the info of the notification in a React Component later.

The data is being received in the main electron file (main.ts)

// Imports of my main.ts

import { app, BrowserWindow,  screen } from 'electron';
import installExtension, {
  REACT_DEVELOPER_TOOLS,
} from 'electron-devtools-installer';
import Pushy from 'pushy-electron';
import { setData } from './redux/reducers/setDataReducer';
import {store} from './redux/store';

This is how i define my dispatch method:

const dispatch = store.dispatch

This is the structure of the data that I’m trying to save in the store:

export interface DataReceived {
  id: string;
  message: [];
}

This is the portion of code where I’m trying to dispatch my action:

** Pushy.setNotificationListener() is a Listener function**

Inside the scope of this function I’m trying to dispatch my action setData(), declared in my reducer.

      Pushy.setNotificationListener((data: DataReceived) => {
        
        const auxData = JSON.stringify(data);
  
        
        dispatch(setData(data))

        // Display an alert with the "message" payload value
        Pushy.alert(mainWindow, 'Received notification: ' + auxData);
      });

My reducer:

setDataReducer.ts

Once my action is dispatched from my main.ts file I can see that the payload has the data that i need to set in my new state of the reducer

import { createSlice } from '@reduxjs/toolkit';

interface DataReceived {
  id: string;
  message: [];
}

let initialState: DataReceived = {
  id: null,
  message: [],
};

export const dataSetter = createSlice({
  name: 'data',
  initialState,
  reducers: {
    setData(state, action) {
      console.log("action.payload: ", action.payload)

      // Result of console.log()
      // *********************
      // action.payload:  {
      //   id: 'd1b42186-64dc-42ca-b88f-64e40c58a1ef',
      //   message: '[{"story":{"id":"f53505c7-ae3c-4390-875a-e65b434b28f5","name":"Soy una historia","title":"Soy un titulo","description":"Soy una descripción","image":"https://storage.googleapis.com/vixonic-dashbX|oard/center","createdAt":2131221313},"tags":[]}]'
      // 

      return {
        ...state,
        id: action.payload.id,
        message: action.payload.message,
      };
    },
  },
});

export const { setData } = dataSetter.actions;

export default dataSetter.reducer;

store.ts


import  {configureStore}  from "@reduxjs/toolkit";
import { useDispatch } from "react-redux";
import { dataSetter } from "./reducers/setDataReducer";

export const store = configureStore({
    reducer: dataSetter.reducer
})

export type RootState = ReturnType<typeof store.getState>

export type AppDispatch  = typeof store.dispatch

export const useAppDispatch : () => AppDispatch = useDispatch

export const selectStory = (state: RootState) => state


As the documentation suggests, i declared my hooks in a separate file to avoid circular import

hooks.ts

 
import {useDispatch, useSelector } from 'react-redux'
import type { TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './store'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector


This is my React component, the const story, is my selector of the state, and I’m passing as an argument the function selectStory() imported from the store file, this function basically is selecting the current state of the Redux store.

I’m trying to render the selected state in a p html tag, and only returns me the initial state of the reducer, and not the new one which is the one that I’m receiving in the payload

import React from 'react';
import { Grid } from '@mui/material';
import StoriesCarousel from '@src/components/Stories/StoriesCarousel';
import { useAppSelector, useAppDispatch } from '../redux/hooks'
import { selectStory } from '@src/redux/store'; 


export interface IStoriesProps {}



const Stories: React.FunctionComponent<IStoriesProps> = (props) => {

  const story = useAppSelector(selectStory)
  const stories: any[] = [
    {
      content: () => (
        
        <div style={{ display: 'flex', flex: 1, justifyContent: 'center' }}>
          <p>{JSON.stringify(story)}</p>
        </div>
      ),
    },
  ];
  return (
    <Grid container item display='flex' justifyContent='center'>
      <StoriesCarousel stories={stories} />
    </Grid>
  );
};

export default Stories;

This is the graphic representation of my problem

image

I’ll be very glad if someone could help me, or telling me if the dispatch method is correctly used.

Regards

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
DevSebas-Codecommented, Aug 9, 2022

Hi @markerikson, thanks for your support, i solved my problem, using the ipcMain and ipcRenderer functions for Electron, So then i could dispatch the action to the front end.

Main.ts (Electron file)


 Pushy.setNotificationListener((data: DataReceived) => {
      const { ipcMain } = require('electron');
      console.log('Data Sended: ', data);
      ipcMain.on('variable-request', function (event, arg) {
        console.log('SENDING....', arg);
        event.sender.send('variable-reply', [data]);
      });

Renderer.tsx (Where my react app is rendered)

import React from 'react';
import ReactDOM from 'react-dom';
import Application from './components/Application';
import { inDev } from './utils/helpers';
import Wrapper from './components/Wrapper';
import { store } from './redux/store';
import { Provider } from 'react-redux';
import { setData } from './redux/reducers/SetVixonicData';

const dispatch = store.dispatch;
const ipcRendererExec = async () => {
  setInterval(() => {
    const ipcRenderer = window.require('electron').ipcRenderer;
    ipcRenderer.send('variable-request', ['somevar', 'anothervar']);
    ipcRenderer.on('variable-reply', function (event, args) {
      console.log('event: ', event);
      dispatch(setData(args));
      console.log('args: ', args);
    });
    console.log('After Function oooo');
  }, 60000);
};

ipcRendererExec();

// Say something
console.log('[ERWT] : Renderer execution started');

// Application to Render
const app = (
  <Provider store={store}>
    <Wrapper>
      <Application title='hola' version='1.0' />
    </Wrapper>
  </Provider>
);

// // store.dispatch({})

// Hot module replacement
if (inDev() && module.hot) module.hot.accept();

// window.Electron.ipcRenderer.once(CHANNEL)


// Render application in DOM
ReactDOM.render(app, document.getElementById('app'));
0reactions
markeriksoncommented, Aug 3, 2022

Unfortunately I’ve never used Electron myself, so I don’t have a good answer here.

I do know there’s tutorials and boilerplates out there that show how to add Redux to an Electron app - the only real suggestion that I can offer atm is to go read through some of those and see what’s different from your current setup.

Per immutable updates, yes, Immer lets you write “mutating” syntax like state.nested.value = 123 instead of {...state, nested: {...state.nested, value: 123}}. See these references:

Read more comments on GitHub >

github_iconTop Results From Across the Web

Store are Not updating when dispatching an action
Basically what I'm doing is making API call, after getting a response successfully,I'm storing the API response in redux store, then I'm ......
Read more >
Can't Dispatch Redux Action From Outside of Component ...
I am having an issue where I am unable to dispatch actions from outside of a component. I have found many other people...
Read more >
Troubleshooting | Redux
Sometimes, you are trying to dispatch an action, but your view does not update. Why does this happen? There may be several reasons...
Read more >
React useReducer Hook ultimate guide - LogRocket Blog
An alternative to the useState Hook, useReducer helps you manage complex state logic in React applications.
Read more >
Strict Mode - React
As explained in this blog post, certain legacy lifecycle methods are unsafe for use in async React applications. However, if your application uses...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found