繁体   English   中英

如何更新componentDidMount内部的状态?

[英]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 }); }); } } 

工作演示: https : //codesandbox.io/embed/728jnjprmq

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执行此操作。 但是,您的代码有几段(不正确)。 让我们从头开始。

首先,将statevalue属性设置为'' ,因此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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM