AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79597088
Accepted
Ninety9Balloons
Ninety9Balloons
Asked: 2025-04-29 02:27:33 +0800 CST2025-04-29 02:27:33 +0800 CST 2025-04-29 02:27:33 +0800 CST

Como posso atualizar um objeto dentro de uma matriz que foi filtrada?

  • 772

Estou trabalhando neste desafio do Frontend Mentor e já dominei a maioria das funcionalidades. Consigo filtrar os dados por suas isActivepropriedades para exibir os itens corretos, independentemente de estarem ativos ou não. O que não consigo descobrir é como atualizar isActiveo status de um item individual e fazer com que ele renderize o aplicativo novamente ao alternar para mover o item para o filtro correto.

Aqui está o código para App.jsx:

function App() {
  const [data, setData] = useState([]);
  const [filteredData, setFilteredData] = useState(data);
  const [activeFilter, setActiveFilter] = useState("All");

  // Fetch and set the data.
  useEffect(() => {
    fetch("../data.json")
      .then((response) => response.json())
      .then((data) => setData(data))
      .catch((error) => console.error("error", error));
  }, []);

  // Filter the data
  useEffect(() => {
    if (activeFilter === "All") {
      setFilteredData(data);
    } else if (activeFilter === "Active") {
      setFilteredData(data.filter((item) => item.isActive === true));
    } else {
      setFilteredData(data.filter((item) => item.isActive === false));
    }
  }, [activeFilter, data]);

  return (
    <div className="w-full h-full bg-linear-to-b from-[#040918] to-[#091540] py-6 px-3 flex flex-col text-white">
      {/* Header */}
      <Header />

      {/* Options */}
      <Options activeFilter={activeFilter} setActiveFilter={setActiveFilter} />

      {/* Cards */}
      {filteredData &&
        filteredData.map((item) => (
          <Card
            logo={item.logo}
            name={item.name}
            description={item.description}
            isActive={item.isActive}
            key={item.name}
            setFilteredData={setFilteredData}
            filteredData={filteredData}
          />
        ))}
    </div>
  );
}

e aqui está Card.jsxcom a chave seletora:

const Card = ({
  logo,
  name,
  description,
  isActive,
  filteredData,
  setFilteredData,
}) => {
  const [activeState, setActiveState] = useState(isActive);

  function handleClick() {
    setActiveState(!activeState);
  }

  return (
    <div className="bg-neutral-700 p-4 rounded-xl border border-neutral-600 mt-4">
      <div className="flex items-start gap-4">
        {/* Logo */}
        <img src={logo} alt="Extension Image" />

        {/* Name and Description */}
        <div className="flex flex-col gap-2 mb-8">
          <h2 className="font-semibold text-xl">{name}</h2>
          <p className="text-sm font-light">{description}</p>
        </div>
      </div>

      {/* Remove Button */}
      <div className="flex justify-between items-center">
        <div className="border border-neutral-600 rounded-full px-3 py-1 flex items-center justify-center">
          <button>Remove</button>
        </div>

        {/* Is Active Toggle */}
        <div className="flex items-center justify-center">
          <label
            htmlFor={`${name}Toggle`}
            className="flex items-center cursor-pointer "
          >
            <div className="relative">
              <input
                id={`${name}Toggle`}
                type="checkbox"
                className="sr-only"
                onClick={handleClick}
              />
              <div
                className={`flex items-center ${
                  activeState ? "bg-red-400 " : "bg-gray-600 "
                } w-11 h-6 rounded-full transition-all px-[2px]`}
              >
                <div
                  className={`bg-white w-5 h-5 rounded-full ${
                    activeState ? "translate-x-5" : "translate-x-0"
                  } transition-all`}
                ></div>
              </div>
            </div>
          </label>
        </div>
      </div>
    </div>
  );
};

Eu estava tentando descobrir uma maneira dentro da handleclickfunção do Card que correspondesse ao nome do card específico com o nome do item filteredDatae... inverter o status dele isActive? Não consegui descobrir como fazer isso funcionar e nem tenho certeza se essa é a melhor maneira de fazer.

javascript
  • 2 2 respostas
  • 63 Views

2 respostas

  • Voted
  1. Best Answer
    David
    2025-04-29T03:07:14+08:002025-04-29T03:07:14+08:00

    Parece que o estado está sendo duplicado. O componente pai está mantendo o estado da lista de itens e do filtro, e passando o isActivevalor do estado para cada componente filho:

    isActive={item.isActive}
    

    Entretanto, o componente filho então duplica esse valor no estado que ele gerencia internamente:

    const [activeState, setActiveState] = useState(isActive);
    

    Atualizar esse estado não tem efeito na lista no componente pai.

    Em vez de rastrear o estado duplicado no componente filho, passe uma função de retorno de chamada para o componente filho que atualizaria o estado no componente pai. Por exemplo, suponha que o componente pai tenha isto:

    const toggleActiveItem = (itemName) => {
      setData(data.map(d => (
        d.name === itemName ? {
          ...d,
          isActive: !d.isActive
        } : d
      )));
    };
    

    (Observação: isso é, obviamente, feito à mão livre e não testado com seus dados. Mas o objetivo geral do acima é atualizar o estado para uma nova matriz de itens em que o isActivesinalizador é alternado para o item que corresponde ao especificado.)

    Em seguida, passe isso para o componente filho para atualizar esse estado:

    isActive={item.isActive}
    toggleIsActive={toggleActiveItem}
    

    Então o componente filho pode removê-lo useStatecompletamente e invocar a função de retorno de chamada que foi passada a ele:

    const Card = ({
      logo,
      name,
      description,
      isActive,
      toggleIsActive,
      filteredData,
      setFilteredData,
    }) => {
      function handleClick() {
        toggleIsActive(name);
      }
    
      //...
    

    Dessa forma, o estado pai é atualizado e os componentes pai e filho relevantes são renderizados novamente com o novo estado.

    • 2
  2. Drew Reese
    2025-04-29T03:21:24+08:002025-04-29T03:21:24+08:00

    Problemas

    Você implementou pelo menos alguns antipadrões do React:

    1. filteredDataé derivado de "estado", por exemplo, derivado das fontes datae activeFilterdo estado de verdade, e, como tal, filteredDatanão deve ser também um estado do React. Você deve calcular o valor filtrado ao renderizar ou memorizar seu valor. Lembre-se de que implementar um acoplamento useState- useEffecttambém é um antipadrão; em quase 100% dos casos de uso, esse acoplamento deve ser substituído pelo useMemohook.
    2. O Cardcomponente não atualiza corretamente a datafonte da verdade no componente pai. Ele recebeu uma isActiveprop, mas também deveria receber um retorno de chamada que trate da atualização do estado no componente pai.

    Sugestões de soluções

    • Filtre o dataestado para calcular o valor dos dados filtrados derivados.
    • Crie um manipulador ativo de alternância que atualize o dataestado e passe isso adiante, Cardem vez do filteredDataestado e do atualizador de estado ( que será removido ).

    Exemplo:

    function App() {
      const [data, setData] = useState([]);
      const [activeFilter, setActiveFilter] = useState("All");
    
      // Fetch and set the data.
      useEffect(() => {
        fetch("../data.json")
          .then((response) => response.json())
          .then((data) => setData(data))
          .catch((error) => console.error("error", error));
      }, []);
    
      const filteredData = useMemo(() => {
        return data.filter(item => {
          if (activeFilter === "Active") {
            return item.isActive;
          }
          return true;
        });
      }, [data, activeFilter]);
    
      const toggleActiveByIndex = (index) => () => {
        setData(data => data.map((item, i) => i === index
          ? { ...item, isActive: !item.isActive }
          : item
        ));
      };
    
      return (
        <div className="w-full h-full bg-linear-to-b from-[#040918] to-[#091540] py-6 px-3 flex flex-col text-white">
          {/* Header */}
          <Header />
    
          {/* Options */}
          <Options activeFilter={activeFilter} setActiveFilter={setActiveFilter} />
    
          {/* Cards */}
          {filteredData.map((item, index) => (
            <Card
              key={item.name}
              item={item}
              toggleActive={toggleActiveByIndex(index)}
            />
          ))}
        </div>
      );
    }
    
    const Card = ({ item, toggleActive }) => {
      const { logo, name, description, isActive } = item;
    
      function handleClick() {
        toggleActive();
      }
    
      return (
        <div className="bg-neutral-700 p-4 rounded-xl border border-neutral-600 mt-4">
          <div className="flex items-start gap-4">
            {/* Logo */}
            <img src={logo} alt="Extension Image" />
    
            {/* Name and Description */}
            <div className="flex flex-col gap-2 mb-8">
              <h2 className="font-semibold text-xl">{name}</h2>
              <p className="text-sm font-light">{description}</p>
            </div>
          </div>
    
          {/* Remove Button */}
          <div className="flex justify-between items-center">
            <div className="border border-neutral-600 rounded-full px-3 py-1 flex items-center justify-center">
              <button>Remove</button>
            </div>
    
            {/* Is Active Toggle */}
            <div className="flex items-center justify-center">
              <label
                htmlFor={`${name}Toggle`}
                className="flex items-center cursor-pointer "
              >
                <div className="relative">
                  <input
                    id={`${name}Toggle`}
                    type="checkbox"
                    className="sr-only"
                    onClick={handleClick}
                  />
                  <div
                    className={`flex items-center ${
                      activeState ? "bg-red-400 " : "bg-gray-600 "
                    } w-11 h-6 rounded-full transition-all px-[2px]`}
                  >
                    <div
                      className={`bg-white w-5 h-5 rounded-full ${
                        activeState ? "translate-x-5" : "translate-x-0"
                      } transition-all`}
                    ></div>
                  </div>
                </div>
              </label>
            </div>
          </div>
        </div>
      );
    };
    
    • 2

relate perguntas

  • classificação de mesclagem não está funcionando - código Javascript: não é possível encontrar o erro mesmo após a depuração

  • método select.remove() funciona estranho [fechado]

  • Sempre um 401 res em useOpenWeather () - react-open-weather lib [duplicado]

  • O elemento de entrada não possui atributo somente leitura, mas os campos ainda não podem ser editados [fechado]

  • Como editar o raio do primeiro nó de um RadialTree D3.js?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve