我有一个React类可以访问API来获取内容。我已经确认数据已经恢复,但它没有重新呈现:
var DealsList = React.createClass({
getInitialState: function() {
return { deals: [] };
},
componentDidMount: function() {
this.loadDealsFromServer();
},
loadDealsFromServer: function() {
var newDeals = [];
chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
newDeals = deals;
});
this.setState({ deals: newDeals });
},
render: function() {
var dealNodes = this.state.deals.map(function(deal, index) {
return (
<Deal deal={deal} key={index} />
);
});
return (
<div className="deals">
<table>
<thead>
<tr>
<td>Name</td>
<td>Amount</td>
<td>Stage</td>
<td>Probability</td>
<td>Status</td>
<td>Exp. Close</td>
</tr>
</thead>
<tbody>
{dealNodes}
</tbody>
</table>
</div>
);
}
});
但是,如果我在下面添加debugger
,则会填充newDeals
,然后一旦我继续,我会看到数据:
loadDealsFromServer: function() {
var newDeals = [];
chrome.runtime.sendMessage({ action: "findDeals", personId: this.props.person.id }, function(deals) {
newDeals = deals;
});
debugger
this.setState({ deals: newDeals });
},
这就是调用交易列表:
var Gmail = React.createClass({
render: function() {
return (
<div className="main">
<div className="panel">
<DealsList person={this.props.person} />
</div>
</div>
);
}
});
答案 0 :(得分:51)
我想补充一点非常简单,但是很容易犯错误的写作:
this.state.something = 'changed';
...然后不理解为什么它没有渲染和谷歌搜索并进入这个页面,只是意识到你应该写的:
this.setState({something: 'changed'});
如果使用setState
更新状态,则React仅触发重新渲染。
答案 1 :(得分:13)
那是因为来自chrome.runtime.sendMessage
的回复是异步的;这是操作的顺序:
var newDeals = [];
// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
// (3) sometime in the future, this function runs,
// but it's too late
newDeals = deals;
});
// (2) this is called immediately, `newDeals` is an empty array
this.setState({ deals: newDeals });
当您使用调试器暂停脚本时,您将给予延长时间来调用回调;当你继续时,数据已经到达并且似乎有效。
要解决此问题,您需要在Chrome扩展程序返回数据后进行setState
调用:
var newDeals = [];
// (1) first chrome.runtime.sendMessage is called, and *registers a callback*
// so that when the data comes back *in the future*
// the function will be called
chrome.runtime.sendMessage({...}, function(deals) {
// (2) sometime in the future, this function runs
newDeals = deals;
// (3) now you can call `setState` with the data
this.setState({ deals: newDeals });
}.bind(this)); // Don't forget to bind(this) (or use an arrow function)
[编辑]
如果这对您不起作用,请查看此问题的其他答案,其中说明了您的组件可能无法更新的其他原因。
答案 2 :(得分:10)
另一个很容易犯的错误,这是我的问题的根源:我编写了自己的shouldComponentUpdate
方法,它没有检查我添加的新状态更改。
答案 3 :(得分:7)
我的情况有点不同。而且我认为很多像我这样的新手都会被难住 - 所以在这里分享。
我的状态变量是一个由 useState 管理的 JSON 对象数组,如下所示:
const [toCompare, setToCompare] = useState([]);
但是,当使用 setToCompare 更新 toCompare 时,如下面的函数所示 - 不会触发重新渲染。并将其移动到不同的组件也不起作用。只有当某些其他事件会触发重新渲染时 - 才会显示更新的列表。
const addUniversityToCompare = async(chiptoadd) =>
{
var currentToCompare = toCompare;
currentToCompare.push(chiptoadd);
setToCompare(currentToCompare);
}
这就是我的解决方案。基本上 - 分配数组是复制引用 - 并且反应不会将其视为更改 - 因为数组的引用没有被更改 - 只有其中的内容。所以在下面的代码中 - 只是使用切片复制了数组 - 没有任何更改 - 并在 mods 之后将其分配回来。工作得很好。
const addUniversityToCompare = async (chiptoadd) => {
var currentToCompare = toCompare.slice();
currentToCompare.push(chiptoadd);
setToCompare(currentToCompare);
}
希望它能帮助像我这样的人。任何人,如果您觉得我错了,请告诉我 - 或者有其他方法。
提前致谢。
答案 4 :(得分:4)
在我的情况下,我正确地调用了this.setState({})
,但是我的功能并没有受到约束,所以它无效。将.bind(this)
添加到函数调用或在构造函数中执行this.foo = this.foo.bind(this)
修复它。
答案 5 :(得分:1)
我在React-Native中遇到了同样的问题,其中API响应&amp;拒绝不更新状态
apiCall().then(function(resp) {
this.setState({data: resp}) // wasn't updating
}
我通过使用箭头功能
更改function
来解决问题
apiCall().then((resp) => {
this.setState({data: resp}) // rendering the view as expected
}
对我来说,这是一个具有约束力的问题。使用箭头函数解决了它,因为箭头函数没有创建它自己的this
,它总是受到它来自的外部环境的限制
答案 6 :(得分:1)
我的问题是,当我应该使用“ React.Component”时,我正在使用“ React.PureComponent”。
答案 7 :(得分:1)
我正在更新并返回传递给我的减速器的相同对象。我通过在像这样返回状态对象之前制作元素的副本来解决这个问题。
Object.assign({}, state)
答案 8 :(得分:0)
研究了很多答案(大多数答案都适合他们的情况),但都没有解决我的问题后,我意识到我的情况有所不同:
在我的怪异场景中,我的组件正在状态内渲染,因此无法更新。 下面是一个简单的示例:
/mnt/
将代码重构为不使其处于可以正常工作的状态:)