[英]How to update state inside componentDidMount?
我正在使用fetch API,并且我想在componentDidMount()(使用onChange)中更新正在模板字符串中使用的const状态。 如何使用onChange更新此值?
import React, {Component} from 'react'
class Data extends Component {
constructor() {
super();
this.state = {
items: {},
value: '',
isLoaded: false
}
}
handleChange(e) {
this.setState({value: e.target.value});
}
componentDidMount() {
const state = this.state.value
fetch(`http://api.timezonedb.com/v2.1/get-time-zone?key=J9X3EOT2EM8U&format=json&by=zone&zone=${state}`)
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
items: json,
})
});
}
render(){
const {isLoaded} = this.state;
if(!isLoaded) {
return <div>Loading...</div>
}
return(
<div>
<select onChange={this.handleChange}>
<option value="America/Chicago">Chicago</option>
<option value="America/Sao_Paulo">São Paulo</option>
</select>
</div>
)
}
}
那么,如何使用onChange更新const状态的值?
安装React组件时会调用componentDidMount()
,并且它只会发生一次。
如果我理解正确,您想对存储在value
状态属性下的value
每次更改调用fetch
,因此componentDidMount
方法不是放置这种逻辑的理想场所。 您可以创建一个名为fetchData
的单独方法,并将该值作为参数传递给它。 然后,您可以在componentDidMount
以及每个值属性更改(在我们的情况下为onChange
事件)中调用该方法。
import React, { Component } from "react"; class Data extends Component { constructor(props) { super(props); this.state = { items: {}, value: "America/Chicago", isLoaded: false }; this.handleChange = this.handleChange.bind(this); } componentDidMount() { const { value } = this.state; this.fetchData(value); } handleChange(event) { const value = event.target.value; this.setState({ value }); this.fetchData(value); } render() { const { isLoaded, value, items } = this.state; if (!isLoaded) { return <div>Loading...</div>; } return ( <div> <select onChange={this.handleChange} value={value}> <option value="America/Chicago">Chicago</option> <option value="America/Sao_Paulo">São Paulo</option> </select> {JSON.stringify(items)} </div> ); } fetchData(value) { fetch( `https://api.timezonedb.com/v2.1/get-time-zone?key=J9X3EOT2EM8U&format=json&by=zone&zone=${value}` ) .then(res => res.json()) .then(json => { this.setState({ isLoaded: true, items: json }); }); } }
Tomasz的代码有2个错误:(1)不获取组件是否已卸载而获取资源。 (2)它首先启动不更新UI的请求。
我将改为执行以下操作:
import React, {Component} from 'react'
class Data extends Component {
constructor() {
super();
this.state = {
items: {},
value: '',
isLoaded: false
}
this._isMounted = false;
// don't forget to bind your methods
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
handleChange(e) {
const value = e.target.value;
this.setState({ value }, () => {
if (!this._isMounted) return;
const url = `http://api.timezonedb.com/v2.1/get-time-zone?key=J9X3EOT2EM8U&format=json&by=zone&zone=${value}`
fetch(url).then((res) => {
if (!this._isMounted) return;
const data = res.json();
this.setState({ isLoaded: true, items: data });
})
});
}
render(){
const { isLoaded } = this.state;
if(!isLoaded) {
return <div>Loading...</div>
}
return(
<div>
<select onChange={this.handleChange}>
<option value="America/Chicago">Chicago</option>
<option value="America/Sao_Paulo">São Paulo</option>
</select>
</div>
)
}
}
假设您要在用户更改select
的值时刷新this.state.items
的值,则可以在onChange
执行此操作。 但是,您的代码有几段(不正确)。 让我们从头开始。
首先,将state
的value
属性设置为''
,因此componentDidMount
函数将看到该值。 我认为那不好,所以让我们将其完全从componentDidMount
中删除。 我们可以将这段代码移到handleChange
函数中,但是仍然需要更改它:
handleChange(e) {
this.setState({value: e.target.value});
fetch(`http://api.timezonedb.com/v2.1/get-time-zone?key=J9X3EOT2EM8U&format=json&by=zone&zone=${e.target.value}`)
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
items: json,
})
});
}
注意我的更改-我们无法从状态访问值,因为setState
是异步的,因此此时尚未更新值。 我们知道价值来自select
。
改善此功能的另一件事是将select
变成受控组件。 为此,您只需要设置要由该组件的状态控制的字段的值即可。 由于您为此使用了onChange
侦听器,因此它使该字段成为受控组件(如果您不使用onChange,则它将是一个只读字段。
state
中的loading
变量似乎未正确使用,我猜您只需要检查'items'中是否有数据。 我现在将其删除,但是您可以回到此位置。
render(){
const {isLoaded} = this.state;
if(!isLoaded) {
return <div>Loading...</div>
}
return(
<div>
<select onChange={this.handleChange}>
<option value="America/Chicago">Chicago</option>
<option value="America/Sao_Paulo">São Paulo</option>
</select>
</div>
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.