【问题标题】:React JS Error: Invalid attempt to destructure non-iterable instanceReact JS 错误:解构不可迭代实例的无效尝试
【发布时间】:2017-06-27 17:45:12
【问题描述】:

我有一个排序过滤器,它采用一个数组来填充选项。试图查看选项value 等于数组中的文本,但我在标题中得到错误:

Invalid attempt to destructure non-iterable instance

我需要将文本作为选项标签中的值传递,以便当用户更新过滤器时,正确的文本会显示给用户所做的选择。

这是我的代码:

function Sorting({by, order, rp}: SortingProps) {
    const opts = [
        ['Price (low)', 'price', 'asc'],
        ['Price (high)', 'price', 'desc'],
        ['Discount (low)', 'discount', 'asc'],
        ['Discount (high)', 'discount', 'desc'],
        ['Most popular', 'arrival', 'latest'],
        ['Most recent', 'arrival', 'latest'],
    ];

    const onChange = (i) => {
        const [text, by, order] = opts[i];
        refresh({so: {[by]: order}});
        /* GA TRACKING */
        ga('send', 'event', 'My Shop Sort By', text, 'Used');
    };

    return (
        <div className={cn(shop.sorting, rp.sorting.fill && shop.sortingFill)}>
            <Select className={shop.sortingSelect} label="Sort By" onChange={onChange} value={`${by}:${order}`}>
                {opts.map(([text], i) =>
                    <Option key={i} value={text}>{text}</Option>
                )}
            </Select>
        </div>
    )
}

【问题讨论】:

  • 错误发生在哪一行?传递给onChange 处理程序的i 的实际值是多少?我猜它是一个 Event 对象,而不是一个整数。
  • 我认为问题出在您正在接受的参数i 中。它不会是一个数字。您不能将其用作数组索引。

标签: reactjs ecmascript-6 destructuring


【解决方案1】:

我多次导致此错误,因为每当我写一个 useState 挂钩时,我经常这样做,我习惯于使用数组来解构这样:

const [ state, setState ] = useState();

但是我的自定义钩子通常会返回一个带有属性的对象:

const { data, isLoading } = useMyCustomFetchApiHook();

有时我不小心写了 [ data, isLoading ] 而不是 { data, isLoading },这会触发此消息,因为当您要解构的对象是对象 {} 时,您要求从数组 [] 中解构属性。

【讨论】:

  • 啊,谢谢!从需要数组语法的 apollo useLazyQuery 切换到不需要数组语法的 useQuery 后,我遇到了这个错误
  • 我有同样的错误,这正是对我有帮助的。 +1
【解决方案2】:

由于逻辑/编码错误而发生错误Invalid attempt to destructure non-iterable instance。下面的javascript用来说明问题:

[aaa,bbb] = somefunc()

somefunc() 被调用时,它必须返回一个至少包含两项的数组。如果不是,则无法将somefunc() 的结果转换为aaabbb 的值。例如代码:

[aaa,bbb] = { 'some': 'object'}

会产生这个错误。

所以这个错误实际上是一个 Javascript 编码错误,它只是发生在 React 代码中,通过打印显示的错误来处理这种情况。见MDN for destructuring assignment documentation

正如@Mayank Shukla 在他的回答中所说,OP 问题的答案是修复这行代码:

const [text, by, order] = opts[i];

通过将其更改为: const [text, by, order] = opts[i.target.value];

根据我的上述描述,应该更清楚opts[i] OP 的原始代码 没有返回至少 3 个项目的数组,因此 javascript 运行时无法设置变量textbyorder。修改/固定的代码确实返回一个数组,因此可以设置变量。

在寻找这个问题的答案后,我意识到其他答案是正确的,我只是在总结错误消息的根本原因。

【讨论】:

    【解决方案3】:

    我也遇到过类似的error,老实说,我犯了一个非常愚蠢的错误,可能是因为编辑器自动完成。

    我不得不使用 useState 钩子,但不知何故由于自动完成,我这样写。

      const [state, setState] = useEffect(defaultValue);
    

    而不是:(。

      const [state, setState] = useState(defaultValue);
    

    希望它会作为error 消息有所帮助,在这种情况下,直到我花了一些时间调试它之前,它根本没有帮助。

    【讨论】:

      【解决方案4】:

      如果有人在使用 useState() 钩子,并且在使用上下文时遇到上述问题。他们可以尝试以下解决方案。

      代替[]

      const [userInfo, setUserInfo] = useContext(userInfoContext);
      

      使用{}

      const {userInfo, setUserInfo} = useContext(userInfoContext); // {} can fix your issue
      

      【讨论】:

        【解决方案5】:

        您没有将参数与 onChange 一起传递,这是很容易错过的事情 - 但是使用选择/选项组合时不太明显。

        它应该看起来像:

        class Sorting extends React.Component {
        
            constructor(props) {
              super(props);
        
              this.opts = [
                  ['Price (low)', 'price', 'asc'],
                  ['Price (high)', 'price', 'desc'],
                  ['Discount (low)', 'discount', 'asc'],
                  ['Discount (high)', 'discount', 'desc'],
                  ['Most popular', 'arrival', 'latest'],
                  ['Most recent', 'arrival', 'latest'],
              ];
        
              this.state = {
                selected: 0, // default value
              }
        
              this.onChange = this.onChange.bind(this);
            }
        
            onChange(i) {
              const [text, by, order] = opts[i.target.value];
            };
        
            render() {
              return (
                  <div>
                      <select onChange={this.onChange} value={this.state.selected}>
                          {this.opts.map(([text], i) =>
                              <option key={i} value={i}>{text}</option>
                          )}
                      </select>
                  </div>
              )
            }
        }
        ReactDOM.render(<Sorting />, document.getElementById("a"));
        

        注意我去掉了你的类和样式以保持简单。另请注意,您使用的是大写的 Select 和 Option - 除非它们是内部自定义组件,否则它们应该是小写的。

        Note2我也介绍了状态,因为select的状态需要存储在某个地方——如果你在这个组件之外维护选择框的状态,你显然可以使用组合props/callbacks 来保持这个值更高一级。

        http://codepen.io/cjke/pen/egPKPB?editors=0010

        【讨论】:

        • 好的,这很接近但是,我收到错误消息“无法读取未定义的属性'值'”......很奇怪
        • 您确定您复制了所有内容...?密码笔工作。我的意思是构造函数中的“绑定”以及更新的值和状态
        • 使用 react 设置这个项目的方式与您通常导出组件的方式不同。我同意使用类和引入状态,但是,这个项目不管理状态并且只使用 react 来渲染组件。它与 PHP 挂钩,所以我无法引入状态 - 网站炸弹。
        • ....如果你不能使用状态,那么,什么都不会更新?完全没有。它也可能是静态 html - 除非我遗漏了什么
        • 哈哈好吧,我不知道该说什么……祝你好运?我认为您不会收到不涉及链上某处状态的答案。如果您正在开发一个 php 应用程序(我知道这可能不是一个选项)并且您只需要在前面添加一点交互性,请考虑只使用 jquery
        【解决方案6】:

        我直接尝试为它分配一个空对象!

        不好:(

          const [state, setState] = {};
        

        很好:)

          const [state, setState] = useState({});
        

        【讨论】:

          【解决方案7】:

          我遇到这个问题是因为我有同样的错误,但为了让它对我有用,我写了

          const [someRef] = useRef(null);
          

          应该是什么时候

          const someRef = useRef(null); // removed the braces []
          

          【讨论】:

            【解决方案8】:

            确保您的 useState 是函数调用而不是数组类型。

            useState('') not useState['']

            【讨论】:

              【解决方案9】:

              问题在于变量i,我将是事件object,使用i.target.value 来获取用户选择的value,还有一件事您使用text 作为@987654327 的值@,而不是使用index,它会起作用,试试这个:

              const onChange = (i) => {
                      const [text, by, order] = opts[i.target.value];
                      refresh({so: {[by]: order}});
                      /* GA TRACKING */
                      ga('send', 'event', 'My Shop Sort By', text, 'Used');
                  };
              
                  return (
                      <div className={cn(shop.sorting, rp.sorting.fill && shop.sortingFill)}>
                          <select className={shop.sortingSelect} label="Sort By" onChange={onChange} value={`${by}:${order}`}>
                              {opts.map(([text], i) =>
                                  <option key={i} value={i}>{text}</option>
                              )}
                          </select>
                      </div>
                  )
              

              检查这个fiddlehttps://jsfiddle.net/5pzcr0ef/

              【讨论】:

              • 它不会是下拉列表中选择的选项的值。它将是一个事件对象。选定的值为event.target.value
              • 是的,我已经有了这个代码,但是如果值等于 i,则该选项不会显示新值
              • 检查更新的ans,删除所有状态值,它工作正常:)
              • 由于我们没有看到Select 组件的代码,我们无法知道i 的值是什么。原生元素(例如 &lt;select&gt;)上的事件处理程序以 Event 对象作为其第一个参数调用,但 &lt;Select&gt;(大写“S”)不是原生元素,因此如果没有看到它的实现,我们就无法知道是什么参数被传递给它。
              • 对不起我的错误,在小提琴中我使用了原生字段,但忘记在这里更改:)
              【解决方案10】:

              Invalid attempt to destructure non-iterable instance 表示您尝试迭代的实例不可迭代。你应该做的是检查opt对象是否是可迭代的并且可以在JSX代码中访问。

              【讨论】:

                【解决方案11】:

                如果您有一个返回数组的async 函数,但您忘记使用await 运行它,也会发生此错误。这将导致该错误:

                const myFunction = async () => {
                  return [1, 2]
                }
                const [num1, num2] = myFunction();
                

                而这将成功:

                const [num1, num2] = await myFunction();
                

                【讨论】:

                  【解决方案12】:

                  在使用 React Context API 时,如果您尝试在未包装在 &lt;ContextProvider&gt; 中的组件中使用 React.useContext(),则可能会出现此错误

                  例如,下面的代码会抛出这个错误:

                  const App = () => {
                     const [state, setState] = React.useContext(MyContext)
                  
                     return (
                       <ContextProvider>
                          <SubComponent />
                       </ContextProvider>
                     );
                  }
                  

                  你可以使用这条线:

                  const [state, setState] = React.useContext(MyContext)
                  

                  SubComponent 内,但不在App 组件内。如果要在App 组件中使用它,请将App 组件放在另一个组件中,并将App 组件包装在&lt;ContextProvider&gt;&lt;/ContextProvider&gt; 中。

                  const App = () => {
                     const [state, setState] = React.useContext(MyContext)
                  
                     return (
                       <div>
                          <SubComponent />
                       </div>);
                  }
                  
                  const Master = () => {
                     <ContextProvider>
                        <App/>
                     </ContextProvider>
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-03-10
                    • 2021-10-10
                    • 1970-01-01
                    • 2016-12-14
                    • 1970-01-01
                    • 2019-06-16
                    • 1970-01-01
                    相关资源
                    最近更新 更多