我点击项目->我从网址:https: // app / api / v1 / asset / $ {id}
获取数据。数据保存在loadItemId
中。我正在将loadItemId
从组件Items
移至组件Details
,然后移至组件AnotherItem
。
每次单击Item
时,道具loadItemId
都会在getDerivedStateFromProps
方法中发生变化。问题:我将单击Element D
->在console.log'true'中看到,然后单击Element E
->它显示在console.log true
和{{ 1}},并且仅显示false
。
尝试创建三元运算符false
。如果{this.state.itemX ['completed'] ? this.start () : ''}
调用函数{this.state.itemX ['completed']
此处的代码:stackblitz
图片:https://imgur.com/a/OBxMKCd
项目
this.start ()
项目
class Items extends Component {
constructor (props) {
super(props);
this.state = {
itemId: null,
loadItemId: ''
}
}
selectItem = (id) => {
this.setState({
itemId: id
})
this.load(id);
}
load = (id) => {
axios.get
axios({
url: `https://app/api/v1/asset/${id}`,
method: "GET",
headers: {
'Authorization': `Bearer ${token}`
}
})
.then(response => {
this.setState({
loadItemId: response.data
});
})
.catch(error => {
console.log(error);
})
}
render () {
return (
<div >
<Item
key={item.id}
item={item}
selectItem={this.selectItem}
>
<Details
loadItemId={this.state.loadTime}
/>
</div>
)
}
详细信息
class Item extends Component {
render () {
return (
<div onClick={() => this.props.selectItem(item.id}>
</div>
)
}
}
另一个项目
class Details extends Component {
constructor() {
super();
}
render () {
return (
<div>
<AnotherItem
loadItemId = {this.props.loadItemId}
/>
</div>
)
}
}
答案 0 :(得分:1)
此处:
int32_t buttons = rawController.ButtonCount();
int32_t switches = rawController.SwitchCount();
int32_t axis = rawController.AxisCount();
std::unique_ptr<bool[]> buttonsArray = std::make_unique<bool[]>(buttons);
std::vector<GameControllerSwitchPosition> switchesArray(switches);
std::vector<double> axisArray(axis);
uint64_t timestamp = rawController.GetCurrentReading(winrt::array_view<bool>(buttonsArray.get(), buttonsArray.get() + buttons), switchesArray, axisArray);
您调用setState(),然后'Item'和'Details'和'AnotherItem'调用其渲染方法。因此您会看到以前的“ loadItemId”的日志。
“加载”方法完成时。在这里:
selectItem = (id) => {
this.setState({
itemId: id
})
this.load(id);
}
再次setState都将状态置于一个位置。加载方法完成后,而不是:
this.setState({
loadItemId: response.data
});
写:
this.setState({
loadItemId: response.data
});
并删除:
this.setState({
itemId: id,
loadItemId: response.data
});
来自“ selectItem”方法。
答案 1 :(得分:0)
需要澄清,但我认为我仍然可以从高层次解决这个问题。正如上面的注释中所建议的,在呈现信息的情况下,似乎您的组件AnotherItem实际上并不需要维护状态来确定调用start()方法的正确时间(尽管由于其他原因,它可能需要处于有状态状态,因为如下所述)。
您似乎要尝试实现的功能(在特定时间调用启动方法)可以仅通过componentDidUpdate生命周期方法对旧/新道具进行比较来完成。正如React文档所提供的,getDerivedStateFromProps实际上是为少数“罕见”情况保留的,我相信这里都没有。相反,似乎是要在接收到新道具并满足一定条件(例如,不等于旧道具)时调用某种方法,或者执行一些计算。可以通过挂接到componentDidUpdate来实现。
class AnotherItem extends Component {
constructor(props) {
super(props);
this.state = {}
}
start = () => { do something, perform a calculation }
// Invoked when new props are passed
componentDidUpdate(prevProps) {
// Test condition to determine whether to call start() method based on new props,
// (can add other conditionals limit number of calls to start, e.g.,
// compare other properties of loadItemId from prevProps and this.props) .
if (this.props.loadItemId && this.props.loadItemId.completed === true) {
//Possibly store result from start() in state if needed
const result = this.start();
}
}
}
render () {
// Render UI, maybe based on updated state/result of start method if
// needed
);
}
}
答案 2 :(得分:0)
您遇到此问题的原因是,您每次点击都会更改state
组件中的Items
,
this.setState({
itemId: id
})
在更改其state
时,Items
组件会重新呈现,从而导致AnotherItem
的前一个state
带有completed
来重新呈现(因为这是子组件) true
(因为您之前单击了元素D)。然后异步请求完成,并用
this.setState({
loadItemId: response.data
});
启动另一个AnotherItem
的{{1}}重新渲染和预期结果。
尝试删除false
中的state
更改,您将获得理想的结果。
我建议您阅读this article,并尝试以不同的方式构造代码。
编辑 您可以通过将加载程序添加到组件中来轻松解决此问题:
selectItem
这样,仅当获取了数据并且不会发生不必要的重新渲染时,才重新渲染selectItem = (id) => {
this.setState({
itemId: id,
loading: true
})
this.load(id);
}
load = (id) => {
axios.get
axios({
url: `https://jsonplaceholder.typicode.com/todos/${id}`,
method: "GET"
})
.then(response => {
this.setState({
loading: false,
loadItemId: response.data
});
})
.catch(error => {
console.log(error);
})
}
render() {
return (
<div >
<ul>
{this.state.items.map((item, index) =>
<Item
key={item.id}
item={item}
selectItem={this.selectItem}
/>
)
}
</ul>
{this.state.loading ? <span>Loading...</span> : <Details
itemId={this.state.itemId}
loadItemId={this.state.loadItemId}
/>}
</div>
)
}
组件。