Реагирует как обновить useState массива при нажатии кнопки

#reactjs #typescript

Вопрос:

Я просмотрел сотню видеороликов и прочитал об этом, и это все еще не имеет для меня смысла. Я пытаюсь обновить массив при нажатии кнопки, но когда я выхожу из массива элементов, он отстает на один, что означает, что он не реагирует и добавляется при следующем рисовании. Кроме того, я завернул свой компонент Employee в div только для того, чтобы иметь возможность добавить к нему «onClick». В идеале я бы хотел, чтобы onClick был в самом компоненте Employee, но это не работает. Спасибо.

 import React, {ReactElement, useState } from "react";
import {TextContainer, Text } from "react-md";
import model from '../Models'
import Employee from './Employee/Employee'
import styles from '../home.module.scss'


export default function Home(): ReactElement {

    const [items, setItems] = useState<Array<any>>([]);


    const addItem = (val:any) => {
        setItems([...items, val ])
        console.log('items :', items)
    }



    return (
          <div className='center'>
          <TextContainer className='center'>
              <Text type='headline-4' style={{color: 'white'}}>Employee List</Text>
          </TextContainer>

          <section className={styles.emp_list}>
              {model.map((props, index) =><div key={index} onClick={() => addItem(props.name)}><Employee key={index} name={props.name} role={props.role} markets={props.markets} image={props.image}/></div>)}
          </section>
          </div>
)}

 

И мой компонент сотрудника:

 import React from "react";
import {MediaContainer} from "@react-md/media";
import styles from './employee.module.scss'
import { Card, CardContent, CardHeader} from "react-md";


function Employee(props: any) {


   return (
        <Card className={styles.emp_card}>
            <CardHeader>
                <div className={styles.emp_text}>
                    <p key={props.name}>Name:amp;nbsp; {props.name}</p>
                    <p key={props.role}>Title:amp;nbsp; {props.role}</p>
                    <p key={props.markets}>Markets:amp;nbsp; {props.markets[0]} {props.markets[1] amp;amp; <span>and {props.markets[1]}</span>}</p>
                </div>
            </CardHeader>
            <CardContent>
                <MediaContainer>
                    <img key={props.image} src={props.image} alt="employee"/>
                </MediaContainer>
            </CardContent>
        </Card>
    )
}


export default Employee;
 

Ответ №1:

Я не думаю, что документация достаточно ясна по этому вопросу, но если вы хотите setState, используя предыдущее состояние, тогда вам следует передать функцию useState. Например:

 const addItem = (val:any) => {
    setItems(prevItems => [...prevItems, val ])
}
 

https://reactjs.org/docs/hooks-reference.html#functional-updates

Комментарии:

1. Спасибо за ответ. Я думал, что передаю функцию. В любом случае, я попробовал ваш путь, и у меня все еще возникает проблема с необходимостью дважды щелкнуть, чтобы он увидел элемент, с помощью которого я обновляю массив. Это должно быть связано с тем, что я помещаю компонент Employee в div и нажимаю на него. Он видит реквизит на этом уровне, но просто работает неправильно.

2. Проблема, которая сводила меня с ума, не имела ничего общего с кодом. Это был консольный журнал, который у меня был внутри функции, которая обновляла состояние, выглядевшее так, как будто оно было одним из последних, но это было не так. Это тоже асинхронно, так что логи консоли обманчивы!! Урок усвоен.