需求描述
在使用 React 的过程中,parent container 在 componentDidMount
中发送一个请求,然后在 render
中将请求的数据传递给 child component , child component 在 render 的时候会会调用一个方法并将 parent 传过来的数据当做参数,最后返回一个数组(前提是传过去的不为空),对于返回的数据会以解构的方式获取。简化后的代码如下:
class Parent extends Component {
componentDidMount () {
this.props.getUser(1)
}
render () {
return <Child user={this.props.user} />
}
const mapStateToProps = state => ({user: state.user})
export default connect(mapStateToProps)(Parent);
}
export default class Child extends Component {
getParams(user){
if(user){
return [user.id,user.name,user.age]
}
}
}
render () {
const [id=0,name='',age=0] = getParams(this.props.user)
return <div/>
}
}
错误
Uncaught (in promise) TypeError: Invalid attempt to destructure non-iterable instance
at my-student-task-status-list-box.js:18
at AssistantSectionList.render (my-student-task-status-view.js:65)
at ReactCompositeComponent.js:793
at measureLifeCyclePerf (ReactCompositeComponent.js:73)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:792)
at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:819)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:359)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:255)
at Object.mountComponent (ReactReconciler.js:43)
at Object.updateChildren (ReactChildReconciler.js:119)
at ReactDOMComponent._reconcilerUpdateChildren (ReactMultiChild.js:204)
at ReactDOMComponent._updateChildren (ReactMultiChild.js:308)
at ReactDOMComponent.updateChildren (ReactMultiChild.js:295)
......
解决过程
- 第一次遇到这个问题,没能从错误信息上获取到比较多的信息,通过观察代码也没能发现哪个地方有问题
- Google 了一下这个错误,发现这个错误是和变量解构有关的,于是再次回到代码
- 发现用到解构的地方只有调用
getParams
这个地方,突然想到,child 在第一次render
的时候,user 中的数据是undefined
,那么这个方法调用后返回的结果就是undefined
,会不会是这个地方的问题,但是我这已经给了初始值呀,于是试一试改了下代码
const [id,name,age] = getParams(this.props.user) || [0,'',0]
- 发现没有报错了,这个地方出错的点是在于变量的解构这块还不够熟悉
总结
以下几种解构方式都会报错
- let [foo] = 1;
- let [foo] = false;
- let [foo] = NaN;
- let [foo] = undefined;
- let [foo] = null;
- let [foo] = {};
前五个是因为将等号右边的值转成对象后不具备 Iterator
接口
最后一个是本身就不具备 Iterator
接口
原生具备 Iterator 接口的数据结构如下。
Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象