Dmitry
Dmitry

Reputation: 867

React hooks doesn't re render component when props changes

I'm trying to implement counter of processed items and I'm using React hooks for this purpose. My component uses variable "itemsProcessed" which is updating asynchronously in action and pushed to the Redux store by using dispatcher.

result = await reader.read();

      itemsProcessed += 1;
      dispatch({
        type: ITEMS_PINGING,
        payload: itemsProcessed,
      });

then in my component I'm using mapStateToProps

    const mapStateToProps = state => ({
      itemsProcessed: state.itemsProcessed,
    });

and useEffect hook to make component rerender my UI when itemsProcessed is changed

    const [pItems, setItemsProcessedCount] = useState('');
.
.
.

    useEffect(() => {
    setItemsProcessedCount(props.itemsProcessed);
  }, [props]);

and UI like this:

<div className={Styles.list}>
    {props.someCondition < 1 ? (
      <div>
        {pItems}...  //if I do this way {props.itemsProcessed} the same result (only three dots, without number of items processed)
      </div>
    ) : (
      _itemsGrid()
    )}
  </div>

The question is why I just see ... on the screen instead of:

1...

then

2...

then

3...

then

4...

and after all the items is processed I just see the list of all items. When I'm trying to debug this case I see how the itemsProcessed is being changed and even see the numbers on the screen (like 2...) But it's only in debug mode. When I close debug console and refresh page I just see ... and nothing else until the list of items is shown. So, React doesn't rerender my pItems after it's changed.

P.S. my reducer looks like this:

const initialState = {
  itemsProcessed: 0,
};

const itemsPinging = (state, action) => {
  return Object.assign({}, state, {
    itemsProcessed: action.payload,
  });
};

export default (state = initialState, action) => {
  switch (action.type) {
    case constants.ITEMS_PINGING:
      return itemsPinging(state, action);
    default:
      return state;
  }
};

Upvotes: 0

Views: 2792

Answers (2)

Ajay Ghosh
Ajay Ghosh

Reputation: 439

Also use the new redux hooks if you are using hooks inside your react app

useDispatch hook useSelector hook

refer redux new Docs. This will provide a better code formatting.

Upvotes: 0

Praneeth Paruchuri
Praneeth Paruchuri

Reputation: 1032

You have two problems in your code:

  1. There's no need to use state for pItems. If the value of pItems gets updated, the component will re-render and you'll have the new values.
  2. You cannot do this {pItems} if pItems is an array or object. Do {JSON.stringify(pItems} and see it shows up (just for testing purposes).

To render a list you should do something like this:

{ pItems.map(item => <div> item </div>) }

Upvotes: 1

Related Questions