Реакция кнопки Обновление значения состояния события нажатия кнопки, но не отраженная в тексте кнопки - PullRequest
2 голосов
/ 23 апреля 2020

Все еще изучаю некоторые веревки React.

У меня есть следующий код, где я отображаю список кнопок:

import React, { useState, useEffect } from 'react';
const MyComponent = (props) => {
  const [buttonList, setButtonList] = useState([]);
  useEffect(() => { getButtonList()}, [])

  const getButtonList = () => {
    let data = [
      {id: 1, name: 'One', selected: false },
      {id: 2, name: 'Two', selected: false },
      {id: 3, name: 'Three', selected: false }
    ]

    setButtonList(data)
  }

  const ButtonItem = ({ item }) => {
    const btnClick = (event) => {
      const id = event.target.value

      buttonList.forEach((el) => {
        el.isSelected = (el.id == id) ? true : false
      })

      setButtonList(buttonList)
      console.log('buttonList', buttonList)
    }

    return (
      <button type="button" 
       className={ "btn mx-2 " + (item.isSelected ? 'btn-primary' : 'btn-outline-primary') }
       onClick={btnClick} value={item.id}>
       {item.name + ' ' + item.isSelected}
      </button>
    )
  }

  return (
    <div className="container-fluid">
      <div className="card mb-3 rounded-lg">
        <div className="card-body">
          {
            buttonList.map(item => (
              <ButtonItem key={item.id} item={item} />
             ))
           }
         </div>
      </div>
    </div>
  )
}

export default MyComponent;

Таким образом, кнопка рендерится:

[ One false ] [ Two false ] [ Three false ]

И когда я нажимаю любую кнопку, на Chrome React Tools я вижу, что значение для isSelected этой кнопки становится true. Я также могу подтвердить, что указанный элемент массива c для кнопки, нажатой в инструментах разработчика для State (под хуками), имеет значение true.

Текст для нажатой кнопки не отображается [ One true ] скажи, нажал ли я на кнопку Один. Что мне здесь не хватает?

PS Обратите внимание, что я также хочу изменить класс кнопки, но я думаю, что эта часть будет решена, если я получу значение кнопки isSelected, которое будет известно всему компоненту.

Код демонстрации: https://codesandbox.io/s/laughing-keller-o5mds?file= / src / App. js: 666-735

Ответы [ 2 ]

3 голосов
/ 23 апреля 2020

Проблема: Вы изменяете объект состояния, а не возвращаете новую ссылку на состояние. Вы также ранее использовали === для сравнения строки id с числовым значением id, которое возвращало значение false для всех сравнений.

Решение: Использование функциональное обновление и array.map для обновления состояния путем возврата нового массива.

const ButtonItem = ({ item }) => {
  const btnClick = event => {
    const id = event.target.value;

    setButtonList(buttons =>
      buttons.map(button => ({
        ...button,
        isSelected: button.id == id
      }))
    );
  };

  ...
};

Edit elastic-ardinghelli-3dw61

Предложение: Вычеркнуть обработчик btnClick, его нужно определить только один раз. Карри id свойство item, так что вы можете использовать ===.

const btnClick = id => event => {
  setButtonList(buttons =>
    buttons.map(button => ({
      ...button,
      isSelected: button.id === id
    }))
  );
};

Обновите привязку обработчика щелчка, чтобы передать идентификатор элемента

const ButtonItem = ({ item }) => {
  return (
    <button
      type="button"
      className={
        "btn mx-2 " +
        (item.isSelected ? "btn-primary" : "btn-outline-primary")
      }
      onClick={btnClick(item.id)} // <-- pass item.id to handler
      value={item.id}
    >
      {item.name + " " + item.isSelected}
    </button>
  );
};
0 голосов
/ 23 апреля 2020

В вашем обработчике btnClick вы изменяете свое состояние, вы должны создать новое значение и присвоить ему вместо:

import React from "react";
import "./styles.css";
import { useState, useEffect } from "react";

const ButtonItem = ({ item, onClick }) => {
  return (
    <button
      type="button"
      className={
        "btn mx-2 " + (item.isSelected ? "btn-primary" : "btn-outline-primary")
      }
      onClick={() => onClick(item.id)}
      value={item.id}
    >
      {item.name + " " + item.isSelected}
    </button>
  );
};

const MyComponent = props => {
  const [buttonList, setButtonList] = useState([]);
  useEffect(() => {
    getButtonList();
  }, []);

  const getButtonList = () => {
    let data = [
      { id: 1, name: "One", isSelected: false },
      { id: 2, name: "Two", isSelected: false },
      { id: 3, name: "Three", isSelected: false }
    ];

    setButtonList(data);
  };

  const btnClick = id => {
    const updatedList = buttonList.map(el => ({
      ...el,
      isSelected: el.id === id
    }));

    setButtonList(updatedList);
    console.log("buttonList", updatedList);
  };

  return (
    <div className="container-fluid">
      <div className="card mb-3 rounded-lg">
        <div className="card-body">
          {buttonList.map(item => (
            <ButtonItem key={item.id} item={item} onClick={btnClick} />
          ))}
        </div>
      </div>
    </div>
  );
};

export default MyComponent;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...