React JS Error:无效尝试解构非可迭代实例

时间:2017-02-09 16:02:52

标签: reactjs ecmascript-6 destructuring

我有一个排序过滤器,它使用一个数组来填充选项。试图看到选项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>
    )
}

11 个答案:

答案 0 :(得分:5)

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

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

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

而不是 :(.

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

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

答案 1 :(得分:3)

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

代替[]

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

使用{}

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

答案 2 :(得分:2)

你没有和你的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的状态需要存储在某个地方 - 如果你在这个组件之外维护选择框的状态,你显然可以使用组合道具/回调将该值保持在一个更高的水平。

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

答案 3 :(得分:1)

问题在于变量i,我将成为事件object,使用i.target.value来获取用户选择的value,还有一件事你使用text options 1}}作为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> ) ,它会起作用,试试这个:

fiddle

选中% your code here % Set limits ylim([-5,5]) % Set colours colormap 'jet' https://jsfiddle.net/5pzcr0ef/

答案 4 :(得分:1)

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

const [someRef] = useRef(null);

应该在什么时候

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

答案 5 :(得分:1)

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

不好:(

  const [state, setState] = {};

好:)

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

答案 6 :(得分:0)

由于逻辑/编码错误,发生错误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的值。修改/固定的代码不会返回数组,因此可以设置变量。

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

我几次导致此错误,因为每当我写一个library(tidyverse) library(htmltab) map(.x = 1:15, .f = function(mynum) {htmltab(doc = "https://en.wikipedia.org/wiki/List_of_Bollywood_films_of_2019", which = mynum, rm_nodata_cols = F)}) -> res Filter(function(x) any(names(x) %in% "Opening"), res) -> out 钩子(我经常这样做)时,我就习惯于使用数组来进行如下分解:

useState

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

const [ state, setState ] = useState();

有时候,我不小心写了const { data, isLoading } = useMyCustomFetchApiHook(); 而不是[ data, isLoading ],这会引起这一消息,因为当您要从中解构的对象是对象{时,您要从数组[]分解属性}。

答案 9 :(得分:0)

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

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

这将成功:

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

答案 10 :(得分:0)

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

useState('') not useState['']