Home > Mobile >  React - state does not update with useReducer
React - state does not update with useReducer

Time:02-20

I want to get the heights of the rendered list items into an array stored in a parent component. It looks fairly simple but still it does not work. From what I see when debugging, the dispatch is fired and the reducer receives the action, but yet the state remains as empty array.

ArticlesMenu.js

import React, { useRef, useState, useEffect, useReducer } from 'react';
import ArticlesMenuItem from './ArticlesMenuItem';

    const reducer = (state, action) => {
        console.log('action', action)
        switch (action.type) {
            case 'add-height': 
                return [...state, action.payload];
            default:
                return state
        }
    }
    
    const ArticlesMenu = ({ articleItems }) => {
        const initialState = [0];
        const [state, dispatch] = useReducer(reducer, initialState);
        const [height, setHeight] = useState('auto'); 
        const renderArticles = () => {
            return articleItems && articleItems.items.map((item, index) => {
                return (
                    <ArticlesMenuItem 
                        path={item.path}    
                        height={height}
                        label={item.label}
                        key={item.id}
                        getHeights={(refHeight) => {
                            console.log('refHeight', refHeight)
                            dispatch({type: 'add_height', payload: refHeight})
                        }}
                    />
                )
            });
        }
    
        console.log('state', state)
    
        return (
            <div id="articles" className="clearfix">
                <h2 className="articles__heading">{articleItems && articleItems.heading}</h2>
                <ul className="articles__list">
                    {renderArticles()}
                </ul>
            </div>
        )
    }
    
    export default ArticlesMenu

ArticlesMenuItem.js

import { useRef, useEffect, useState } from 'react';
import { Link } from 'react-router-dom';

const ArticlesMenuItem = ({ path, id, label, height, getHeights}) => {
    const ref = useRef();

    useEffect(() => {
        getHeights(ref.current.clientHeight)
    },[])

    return (
        <li className="articles__item" ref={ref} style={{height: height}}>
            <Link to={path} className="articles__link" >{label}</Link>
        </li>
    )
}

export default ArticlesMenuItem;

CodePudding user response:

Your dispatch action type is 'add_height' but in your reducer the action type is 'add-height' so the way use default that return state and your initial state is an empty array. You need to change your dispatch action type for same string that reducer annotation. For not reproduce this error use a reference (const ADD_HEIGHT_ACTION = 'add-height' and use on reducer and dispatch.

  • Related