react-boilerplate/react-boilerplate-typescript

`useInjectReducer` generates error in the console.

idMolotov opened this issue · 10 comments

Description

I've got error message in the browser console.

I've generate two components with npm run generate command:

  • NewPage
  • SecondPage

with their own reducer's.

Now, when I switching from Home page to the NewPage and then to the SecondPage I've got message:

Warning: Cannot update a component from inside the function body of a different component.
....

in this line:

  useInjectReducer({ key: 'SecondPage', reducer: reducer });

Steps to reproduce

Steps to reproduce the behavior:
0) setup boilerplate 4.1

  1. npm run generate for two containers
  • NewPage
  • SecondPage
  1. add to app/components/Header/index.tsx
        <HeaderLink to="/new-page">
          new page
        </HeaderLink>
        <HeaderLink to="/second-page">
          second page
        </HeaderLink>

Expected behavior
Need to have no warnings or errors from react in the console.

Screenshots
Screenshot 2020-04-08 10 01 42

Versions

  • React-Boilerplate:
  "name": "react-boilerplate-typescript",
  "version": "4.1.0",
  "description": "A highly scalable, offline-first foundation with the best DX and a focus on performance and best practices",
  "repository": {
    "type": "git",
    "url": "git://github.com/react-boilerplate/react-boilerplate-typescript.git"
  },
  "engines": {
    "npm": ">=6.4.1",
    "node": ">=10.13.0"
  },
  • Node/NPM:
node -v
v10.16.0
npm -v
6.9.0
  • Browser:
    Google Chrome
    Version 84.0.4104.0 (Official Build) canary (64-bit)

If I add reducers init to app/configureStore.ts

  const store = createStore(
    createReducer({
      newPage: NewPage,
      secondPage: SecondPage,
    }),
    initialState,
    enhancer,
  ) as InjectedStore;

and remove useInjectReducer({ key: 'newPage', reducer: reducer }); from corresponding components - everything looks ok.

Please, can you advice about using the reducer injectors.
Is this 'fix` is a correct workaround about this issue?

Can you show me the code of the pages you generate its hard to tell whats wrong judging by the error only.

@Can-Sahin

nothing changed in the pages/containers after generation. So, I think they are exacatly the same as in the templates.

/*
 *
 * NewPage
 *
 */

import React from 'react';
import { FormattedMessage } from 'react-intl';
import { useSelector, useDispatch } from 'react-redux';
import { createStructuredSelector } from 'reselect';

import { useInjectReducer, useInjectSaga } from 'redux-injectors';

import makeSelectNewPage from './selectors';
import reducer from './reducer';
import saga from './saga';
import messages from './messages';

const stateSelector = createStructuredSelector({
  newPage: makeSelectNewPage(),
});

interface Props {}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function NewPage(props: Props) {
  // useInjectReducer({ key: 'newPage', reducer: reducer });
  useInjectSaga({ key: 'newPage', saga: saga });

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const { newPage } = useSelector(stateSelector);
  const dispatch = useDispatch(); // eslint-disable-line @typescript-eslint/no-unused-vars
  return (
    <div>
      <FormattedMessage {...messages.header} />
    </div>
  );
}

export default NewPage;

useInjectReducer({ key: 'newPage', reducer: reducer }); is the newPage key same for both of the generated pages?

@Can-Sahin

no, other page is using own names

/*
 *
 * SecondPage
 *
 */

import React from 'react';
import { FormattedMessage } from 'react-intl';
import { useSelector, useDispatch } from 'react-redux';
import { createStructuredSelector } from 'reselect';

import { useInjectReducer, useInjectSaga } from 'redux-injectors';

import makeSelectSecondPage from './selectors';
import reducer from './reducer';
import saga from './saga';
import messages from './messages';

const stateSelector = createStructuredSelector({
  secondPage: makeSelectSecondPage(),
});

interface Props {}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function SecondPage(props: Props) {
  useInjectReducer({ key: 'secondPage', reducer: reducer });
  useInjectSaga({ key: 'secondPage', saga: saga });

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const { secondPage } = useSelector(stateSelector);
  const dispatch = useDispatch(); // eslint-disable-line @typescript-eslint/no-unused-vars
  return (
    <div>
      <FormattedMessage {...messages.header} />
    </div>
  );
}

export default SecondPage;

Also, if I click in some other oder, I will got same error message for the second page.

Then I don't know why at this point. If you give a sample repo to download I can check if its a a bug you introduce or it comes from boilerplate's logic.

@Can-Sahin

is this will helps you?

Repo:
https://github.com/idMolotov/rbt-examples

Commit with changes made on initial setup:
idMolotov/rbt-examples@a5b1371

Your selectors aren't selecting their slices but just return the root state object.

Go to your selectors.ts in your new page container and make sure its like

const selectSecondPageDomain = (state: ApplicationRootState) =>
  state.secondPage || initialState;

Notice the .secondPage. So you work on your slice

Read more about the error here

I will also check if the generators can include this by default.

@Can-Sahin

Big thanks for your support!

Very nice.