【问题标题】:Uncaught TypeError: Object is not iterable (cannot read property Symbol(Symbol.iterator)) in my React projectUncaught TypeError: Object is not iterable (cannot read property Symbol(Symbol.iterator)) 在我的 React 项目中
【发布时间】:2022-07-09 00:31:01
【问题描述】:

我是上下文 API 的新手,并试图让我的代码正常工作。我收到错误:

Uncaught TypeError: Object is not iterable (cannot read property Symbol(Symbol.iterator))

你们中的一些好人会帮忙解决这个问题吗?

initialUserState 记录一个如下所示的对象:{name: nanny}

我的上下文文件是:

import { createContext, useState } from "react";

const initialUserState = JSON.parse(localStorage.getItem("user"));
console.log(initialUserState);
const initialFormValues = {
  video: "Video.mp4",
  hourly: "",
  ageRange: [],
  car: "",
  languages: [],
  homework: "",
  license: "",
  preference: "",
  vaccination: "",
  radius: "",
  booked: "",
  fileUpload: "file.jpg",
};

export const Global = createContext();

export default function GlobalContext({ children }) {
  const [state, setState] = useState(initialUserState);
  const [values, setValues] = useState(initialFormValues); //setting form state
  const [radioSelected, setRadioSelected] = useState();

  const changeState = (newState = {}) => {
    const tempState = { ...state, ...newState };
    setState(tempState);
    localStorage.setItem("user", JSON.stringify(tempState));
  };

  return (
    <Global.Provider
      value={[
        { ...state },
        changeState,
        values,
        setValues,
        radioSelected,
        setRadioSelected,
      ]}
    >
      {children}
    </Global.Provider>
  );
}

然后我从哪里获取状态,initialFormValues 没有登录控制台:

const HourlyRate = () => {

  //context API

  const [values, setValues] = useContext(GlobalContext); **//this is where the error is being flagged from**

  //handle form value changes
  const handleChange = (e) => {
    e.preventDefault();

    const { name, value } = e.target;
    setValues({ ...values, [name]: value });
  };

  return (
    <div className="sub-settings-div">
      <Link className="back" to="/video-upload">
        <span>
          <ArrowBackIcon />
        </span>
        Back
      </Link>
      <h3 className="sub-settings-header">{t("common.title")}</h3>
      <h2 className="sub-settings-sub-header">{t("hourly.subTitle")}</h2>
      <p className="range">(10.45 &euro; - 20 &euro;) </p>
      <form className="input">
        <TextField
          className="input-field"
          required
          id="outlined-required"
          label="Hourly Rate"
          name="hourly"
          value={values.hourly}
          onChange={handleChange}
        />
      </form>
      <div className="nav-btns">
        <Link to="/video-upload" className="prev-link">
          <button className="prev">{t("buttons.back")}</button>
        </Link>
        <Link to="/age-range" className="next-link">
          <button className="next">
            {t("buttons.next")}
            <span>
              <ArrowForwardIcon />
            </span>
          </button>
        </Link>
      </div>
    </div>
  );
};

export default HourlyRate;

【问题讨论】:

    标签: reactjs react-hooks react-context use-context


    【解决方案1】:

    我看到的几个问题:

    1. 您将上下文提供程序组件GlobalContext 传递给useContext 钩子const [values, setValues] = useContext(GlobalContext);
    2. 上下文值是一个数组,因此在使用数组解构时,数组元素的顺序很重要。

    为上下文使用正确的变量。您可能希望为上下文指定 GlobalContext 名称,并将提供程序重命名为 GlobalProvider。我建议还使用一个对象作为上下文值来消除数组元素顺序解构问题。

    export const GlobalContext = createContext();
    
    export default function GlobalProvider({ children }) {
      const [state, setState] = useState(initialUserState);
      const [values, setValues] = useState(initialFormValues); //setting form state
      const [radioSelected, setRadioSelected] = useState();
    
      const changeState = (newState = {}) => {
        const tempState = { ...state, ...newState };
        setState(tempState);
        localStorage.setItem("user", JSON.stringify(tempState));
      };
    
      return (
        <Global.Provider
          value={{
            state,
            changeState,
            values,
            setValues,
            radioSelected,
            setRadioSelected,
          }}
        >
          {children}
        </Global.Provider>
      );
    }
    

    然后假设您的主要App 组件正确包装在GlobalProvider 中,请使用挂钩中的对象解构。

    const { values, setValues } = useContext(GlobalContext);
    

    【讨论】:

      【解决方案2】:

      你的价值是:

      [
          { ...state },
          changeState,
          values,
          setValues,
          radioSelected,
          setRadioSelected,
        ]
      

      这一行:const [values, setValues] = useContext(GlobalContext); 将解构值(数组),但解构数组和对象之间存在关键区别: 对于数组,解构是按顺序进行的(与按名称命名的对象不同),这意味着: values 变量将保存第一个对象 { ...state } 不可迭代

      如果你的值是一个对象:

      {
          state,
          changeState,
          values,
          setValues,
          radioSelected,
          setRadioSelected,
        }
      

      useContext 将是const {state,setValues} = useContext(GlobalContext);

      【讨论】:

        【解决方案3】:

        如果您正在编写自己的 React 钩子(use... 函数),那么这可能会根据您在自定义钩子中返回值的方式发生。

        例如,返回一个数组期望和数组:

        const [count, setCount, increment] = useCount()
        // requires
        return [count, setCount, increment]
        

        同样,返回一个对象需要一个对象:

        const {count, setCount, increment} = useCount()
        // requires
        return {count, setCount, increment}
        

        这两者的任何混合都会导致如下错误:

        Uncaught TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
        

        例如:

        const [count, setCount, increment] = useCount()
        // errors with
        return {count, setCount, increment}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-11-06
          • 2020-12-14
          • 2021-05-21
          • 2021-10-22
          • 2019-08-13
          • 2020-12-02
          • 2022-11-28
          • 1970-01-01
          相关资源
          最近更新 更多