我正在使用react和redux但是我得到以下异常:
foo.js:10未捕获错误:findComponentRoot(...,。0。$ data.0.0。$ 22):无法找到元素。这可能意味着DOM意外地发生了变异(例如,通过浏览器),通常是因为忘记了使用表时,嵌套标记如
检查元素的子节点<form>
,<p>
或<a>
,或者使用非父母中的-SVG元素。尝试使用React ID
当我按下面按钮时:
let mapStateToProps = (state) => {
const user = state.user.get("user");
return {
data: state.data.get("data"),
loading: state.pausedAlarms.get("loading"),
userId: user&&user.id
}
};
let mapActionsToProps = (dispatch) => {
return {
getData() {
dispatch(getData());
},
selectUser(user){
dispatch(selectUser(user));
},
};
};
let Foo = React.createClass({
componentWillMount() {
this.props["getData"]();
},
shouldComponentUpdate(nextProps, nextState) {
if(nextProps["userId"] !== this.props["userId"]) {
nextProps["getData"]();
}
return true;
},
render() {
const {
data,
selectUser,
loading
} = this.props;
if (loading) {
return (
<div id="3" key="3">LOADING</div>
);
}
else if (data){
return (
<div id="1" key="1">
<div id="11" key="11">
HEADER
</div>
<button
id="2"
key="22"
onClick={
e => {
selectUser(new User({id:1,name:"Foo"}))
}
}
>Click</button>
</div>
);
}
else{
return null;
}
}
});
按下按钮将调度动作selectUser,它会使用userId
的新值更新我的redux状态。这会导致shouldComponentUpdate调用nextProps["getData"]();
。操作getData
首先通过调度,以便在reducer中将loading
设置为true。
上面的代码按预期呈现,只是我在控制台窗口中看到异常。
如果我改为:
shouldComponentUpdate(nextProps,nextState){
if(nextProps["userId"] !== this.props["userId"]) {
nextProps["getData"]();
return false;
}
return true;
},
我的代码按预期工作但没有例外。 我究竟做错了什么?我该如何调试此问题?
答案 0 :(得分:1)
我想问题是你在shouldComponentUpdate
发送了一个动作。
您可以在componentWillReceiveProps
:
componentWillReceiveProps(nextProps) {
if(nextProps["userId"] !== this.props["userId"]) {
nextProps["getData"]();
}
}
shouldComponentUpdate
旨在确定是否应更新组件,而不是更新状态。看看下面的SO讨论:
Is it OK to call setState from within shouldComponentUpdate?
更新1
检查问题是否由渲染结构引起。尝试简化它(删除键,mouniting / unmounting节点等):
getData() {
return (
<div>
HEADER
<button onClick={ e => { selectUser(new User({id:1,name:"Foo"})) } }>Click</button>
</div>
);
}
render() {
const {
data,
selectUser,
loading
} = this.props;
return (
<div>
{ loading ? 'LOADING' : null }
{ (! loading) && data ? this.getData() : null }
</div>
);
}