多个变体循环中的 useState 不起作用 - 与 NextJs 反应

useState in multiple variants loop not working - React with NextJs

我的一个组件中有多个变体,我希望如果我单击任何变体,它应该向其添加 active class 并从另一个组件中删除 active class 。但是我对在多个变体循环中使用状态如何发生感到困惑。
这是我的代码:

import { useState } from "react";

const Variants = () => {
    // Sample Variants Object - But in real it's coming from Wordpress back-end GraphQL
    const vats = {
        "Tech": ['3G', '5G'],
        "Color": ['Red', 'Gray']
    }

    const [selectedTech, techToChange] = useState(null);

    return (
        <div>
            {vats && (
                <div>
                    {Object.keys(vats).map((key, value) => (
                        <div key={key}>
                            <div><b>{key}</b></div>
                            {vats[key].map((val) => (
                                <div key={val} onClick={() => techToChange('active')}>
                                    <label
                                        className="cursor-pointer bg-yellow-100"
                                    >
                                        {val} - {selectedTech}
                                    </label>
                                </div>
                            ))}
                            <hr/>
                        </div>
                    ))}
                </div>
            )}
            <hr />
        </div>
    )
}

你可以在我的代码中看到,有2个名为Tech & Color的变体,例如;如果我点击 tech 的 3G,它应该向其添加 active class 并从 5G 中删除 active class & 如果我点击 Red 它应该添加active class 并从 Gray 中删除 active class。有人可以帮我做吗?我卡住了

这是 return 代码。您需要传递 val 来设置 selectedTech 状态变量的状态,然后将实际值与其进行比较以设置活动 class。

const [selectedTech, techToChange] = useState([]);

    const selectOps = (key,val) => {
        let existing = selectedTech;
        let idx = existing.findIndex(i => i.key===key);
        console.log(idx);
        
        if(idx > -1){
         existing.splice(idx,1);
         console.log(idx, existing);
        }
        techToChange([...existing, {key,val}]);
    }

    return (
        <div>
            {vats && (
                <div>
                    {Object.keys(vats).map((key, value) => (
                        <div key={key}>
                            <div><b>{key}</b></div>
                            {vats[key].map((val) => (
                                <div key={val} onClick={() => selectOps(key,val)}>
                                    <label
                                        className={`cursor-pointer bg-yellow-100 ${selectedTech.some(s => s.val===val) ? 'active' : undefined}`}
                                    >
                                        {val}
                                    </label>
                                </div>
                            ))}
                            <hr/>
                        </div>
                    ))}
                </div>
            )}
            <hr />
        </div>
    )
来自 react-use

useMap 非常适合您现有的代码:

const [vats, {set, setAll, remove, reset}] = useMap({
    "Tech": ['3G', '5G'],
    "Color": ['Red', 'Gray']
}
...

{Object.keys(vats).map((key, value) => (

...
     <div key={val} onClick={() => set(key, val)}>

您只是将 selectedTech 设置为 'active'——这只是一个字符串,不会在点击的技术和处于状态的 selectedTech 之间创建任何类型的关系。

要解决此问题,您需要将 selectedTech 设置为您单击的那个的实际 val。要添加你想要的变体分离,状态可以模仿你的变体的形状并且是一个对象。因此,您可以将 selectedTech[variant] 设置为您单击的值,而不是直接设置 selectedTech

然后,通过一些评估,您可以打印出字符串,active 当您单击一个时。

import { useState } from "react";

export default () => {
  // Sample Variants Object - But in real it's coming from Wordpress back-end GraphQL
    const vats = {
    Tech: ["3G", "5G"],
    Color: ["Red", "Gray"]
  };
  const initialState = Object.fromEntries(Object.keys(vats).map((key)=> [key, null]));  const [selectedTech, techToChange] = useState(initialState);

  return (
    <div>
      {vats && (
        <div>
          {Object.keys(vats).map((key, value) => (
            <div key={key}>
              <div>
                <b>{key}</b>
              </div>
              {vats[key].map((val) => (
                <div key={val} onClick={() => techToChange((c) => ({...c, [key]: val}))}>
                  <label className="cursor-pointer bg-yellow-100">
                    {val} - {selectedTech[key] === val ? "active" : null}
                  </label>
                </div>
              ))}
              <hr />
            </div>
          ))}
        </div>
      )}
      <hr />
    </div>
  );
};

代码沙箱:https://codesandbox.io/s/inspiring-kare-hsphp?file=/src/App.js

这是使用 useRef 和其他一些您可能会觉得有用的东西的示例:

import React, { useState, useRef, useEffect} from "react";

const Variants = () => {
// Sample Variants Object - But in real it's coming from Wordpress back- 
end GraphQL
const vats = {
    "Tech": ['3G', '5G'],
    "Color": ['Red', 'Gray']
}

const labelRef = useRef();
const [selectedTech, techToChange] = useState("");
const [selectedColor, colorToChange] = useState("");

useEffect(()=>{
  console.log(selectedColor);
  if(labelRef.current.innerHTML.trim() === selectedColor) {
    labelRef.current.className ="other class";
  }
  else {
    labelRef.current.className ="cursor-pointer bg-yellow-100";
  }
},
[selectedColor, labelRef])

useEffect(()=>{
  console.log(selectedTech);
  if(labelRef.current.innerHTML.trim() === selectedTech) {
    labelRef.current.className ="other class";
  }
  else {
    labelRef.current.className ="cursor-pointer bg-yellow-100";
  }
},
[selectedTech, labelRef])


return (
    <div>
        {vats && (
            <div>
                {Object.keys(vats).map((key, value) => (
                    <div key={key}>
                        <div><b>{key}</b></div>
                        {vats[key].map((val) => (
                            <div key={val} onClick={(e) => {
                              
                              if(key==="Tech") {
                             //console.log(e.target.innerHTML); 
                             techToChange(e.target.innerHTML.trim());
                             labelRef.current = e.target;
                             //console.log(val.trim(),selectedTech.trim());
                              }
                              else if(key==="Color")
                              {
                              colorToChange(e.target.innerHTML.trim())
                              labelRef.current = e.target;
                              }
                            }
                             
                            }>
                              
                                <label ref={labelRef}
                                    className="cursor-pointer bg-yellow-100"
                                >{val}                                                                     
                                </label>
                              
                            </div>
                        ))}
                        <hr/>
                    </div>
                ))}
            </div>
        )}
        <hr />
    </div>
)
}

export default Variants;