【问题标题】:typescript err: must have a '[Symbol.iterator]()' method that returns an iterator when using react usereducer hook in context-why?typescript err: must have a '[Symbol.iterator]()' method that return an iterator when using react usereducer hook in context-为什么?
【发布时间】:2021-05-16 23:13:26
【问题描述】:

我使用的是打字稿,不太熟悉,并且当我使用 context 和 useReducer 挂钩时出现以下错误 - 特别是对于我的调度方法,我得到了这个:

contextProps must have a '[Symbol.iterator]()' method that returns an iterator.

我试图研究它,但不知道该怎么做。我想这是因为 const [state, dispatch] = useContext(GlobalState);由于数组,我需要指定一些东西。 此外,我在价值方面得到了一个 ts 错误

  <GlobalState.Provider value={[state, dispatch]}>

(参见下面的代码)。不知何故,当我拥有一个数组时,我在 ContextProps 中定义的所有属性都丢失了。 任何帮助都会很有帮助!

//context.js file
export interface ProjectProps {
  projects: string[]
}

export interface ContextProps extends ProjectProps {
  show: boolean
  posts: string[]
  //...
}

const initialState = {
  posts: [],
  show: false
  //...
};

export const GlobalState = React.createContext<ContextProps | null>(
  initialState
)

const reducer = (state, action) => {
  switch (action.type) {
    case "SHOW":
      return { ...state, show: !state.show }

    default:
      return state
  }
}

const Store: React.FC<{ children: React.ReactNode }> = ({children}) => {
  const [state, dispatch] = useReducer(Reducer, initialState);
  return (
      <GlobalState.Provider value={[state, dispatch]}>
          {children}
      </GlobalState.Provider>
  )
};


const App = () => {
  return (
      <Store>
          <Header/>
          <Blog/>
      </Store>
  );
};

const Blog = () => {

  const [state, dispatch] = useContext(GlobalState);

  return (
      <div>
        <button onClick={dispatch({type: "SHOW"})}></button>
        {state.show ? <p>hello</p> : null }
      </div>
  );
};

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    您提供的代码似乎有一些问题。

    首先,我会先添加更多类型。
    尤其是reducerconst [state, dispatch] = useReducer(reducer, initialState); 的参数和输出(注意:我假设reducer 在这里是小写的,尽管它在您的代码示例中是Reducer

    接下来,我认为与您的使用方式相比,您的上下文定义存在问题。
    如果您想将statedispatch 都提供给您的Provider(如&lt;GlobalState.Provider value={[state, dispatch]}&gt; 所示,那么我希望您的上下文定义看起来更像这样:

    interface Context {
      state: {
        show: boolean;
        posts: string[];
        //...
      };
      dispatch: React.Dispatch<any>; // I don't know what any should be in your case
    }
    

    请注意:

    • 您的提供商将更改为: &lt;GlobalState.Provider value={{state, dispatch}}&gt;
    • 用法将更改为:const {state, dispatch} = useContext(GlobalState);

    如果您确实想使用[state, dispatch] 作为上下文的输出,那么您应该使用type Context = [{show: boolean; posts: string[];}, React.Dispatch&lt;any&gt;] 之类的类型,而不是interface

    最后,像... must have a '[Symbol.iterator]()' method that returns an iterator. 这样的错误通常意味着您正在迭代(使用forwhile,...)通过一个不是可以迭代的类型的对象。可以迭代的类型示例是 Array
    如果您想获得有关最后一个错误的更多指导,那么如果您能准确指定此错误发生的位置,将会有所帮助。

    【讨论】:

    • 谢谢。无论我在哪里使用上下文(--> const [state, dispatch] = useContext(GlobalState) for state AND/OR dispatch,我都会得到 [Symbol.iterator]。此外,我没有添加更多类型,因为它与我的问题,但谢谢。我也尝试了你的上下文定义,但它只会给我错误
    • 其实,现在想想const [state, dispatch] = useContext(GlobalState)。您将此处的数组破坏为 2 个变量。但是GlobalState 的类型来自React.createContext&lt;ContextProps | null&gt;( initialState )。哪个不是数组,不能迭代。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    相关资源
    最近更新 更多