繁体   English   中英

如何正确更改 object 的 state?

[英]How to change state of object correctly?

我有一个 object,我想在单击按钮时更改值。 无论我做什么,我只能在第二次点击时更改 state。 第一次点击总是为我返回初始值。 有人可以指导我这里有什么问题吗?

初始 state:

const [currencyResult, setCurrencyResult] = useState({
        amount: "1",
        currencyFrom: "EUR",
        currencyTo: "USD",
        multipliedAmount: "",
        date: ""
    });

onclick:

setCurrencyResult({
                amount: currencyResult.amount,
                currencyFrom: currencyResult.currencyFrom,
                currencyTo: currencyResult.currencyTo,
                multipliedAmount: currencyRate * currencyResult.amount,
                date: Date.now()
            })

整个代码是:

import React, { useState, useEffect } from 'react';
import { Form, Icon } from 'semantic-ui-react';
import { Link } from 'react-router-dom';
import ShowResult from './ShowResult';
import "../styles/HomePage.css"


const HomePage = (props) => {
    const options = [
        { key: 'EUR', value: 'EUR', text: 'EUR' },
        { key: 'USD', value: 'USD', text: 'USD' },
        { key: 'CHF', value: 'CHF', text: 'CHF' },
    ];
    const baseUrl = `https://api.exchangeratesapi.io/latest?base=`
    const [currencyResult, setCurrencyResult] = useState({
        amount: "1",
        currencyFrom: "EUR",
        currencyTo: "USD",
        multipliedAmount: "",
        date: ""
    });
    const [currencyDatabase, setCurrencyDatabase] = useState([]);
    const [hasError, setHasError] = useState(false);
    const [errorMessage, setErrorMessage] = useState("");
    const { amount, currencyFrom, currencyTo, multipliedAmount, date } = currencyResult;
    const [currencyRate, setCurrencyRate] = useState("");
    const [clicked, setClicked] = useState(false);
    const formValidation = () => {

        if (currencyResult.currencyFrom === currencyResult.currencyTo) setErrorMessage("Equal currencies")
        if (!currencyResult.amount) setErrorMessage("no number given")
        if (currencyResult.amount.charAt[0] === "-") setErrorMessage("no minus numbers")
        if (currencyResult.amount === "0") setErrorMessage("can't convert 0")
        if (errorMessage) setHasError(true)
    }

    const calculationHandler = async () => {
        formValidation()

        if (hasError) {
            return
        } else {
            setClicked(!false)
            const fetchData = await fetch(`${baseUrl}${currencyResult.currencyFrom}&symbols=${currencyResult.currencyTo}`);
            const response = await fetchData.json();
            setCurrencyRate(await Object.values(response.rates)[0])
            setCurrencyDatabase([...currencyDatabase, currencyResult])
            setCurrencyResult({
                amount: currencyResult.amount,
                currencyFrom: currencyResult.currencyFrom,
                currencyTo: currencyResult.currencyTo,
                multipliedAmount: currencyRate * currencyResult.amount,
                date: Date.now()
            })
        }
    }





    if (currencyDatabase) props.getCalculations(currencyDatabase);


    const changeCurrency = () => {
        setCurrencyResult({
            ...currencyResult,
            currencyTo: currencyResult.currencyTo
        })
        setCurrencyResult({
            ...currencyResult,
            currencyFrom: currencyResult.currencyFrom
        })
    }

    return (
        <div className="app">
            <div className="header">
                <h1 className="headline">Convert currencies in real-time.</h1>
            </div>
            <div className="form-content">

                <Form className="box-background">
                    <Form.Group style={{ margin: "auto" }} >
                        <Form.Input
                            required
                            label='Amount'
                            placeholder='Amount'
                            value={currencyResult.amount}
                            onChange={(e, { value }) => setCurrencyResult({
                                ...currencyResult,
                                amount: value
                            })}
                            type="number"
                        />
                        <Form.Select
                            required
                            placeholder="From"
                            label="From"
                            value={currencyResult.currencyFrom}
                            onChange={(e, { value }) => setCurrencyResult({
                                ...currencyResult,
                                currencyFrom: value
                            })}
                            options={options}
                        />
                        <Icon name="exchange" onClick={changeCurrency} size="large" />
                        <Form.Select
                            required
                            placeholder="To"
                            label="To"
                            value={currencyResult.currencyTo}
                            onChange={(e, { value }) => setCurrencyResult({
                                ...currencyResult,
                                currencyTo: value
                            })}
                            options={options}
                        />
                        <Form.Button
                            className="btn-div"
                            onClick={calculationHandler}>
                            Convert
                            </Form.Button>
                    </Form.Group>
                    <Form.Field className="error-msg">
                        {hasError ? <p>{errorMessage}</p> : null}
                    </Form.Field>
                </Form>
                <Link to="/result" className="conversion-history">
                    <span>View conversion history {">"}</span>
                </Link>
            </div>
            {currencyResult && <ShowResult currencyResult={currencyResult} />}
        </div>
    );
}

export default HomePage;

使用功能更新。

如果使用以前的 state 计算新的 state,则您可以 [并且应该] 将 function 传递给 setState。 function 将接收先前的值,并返回更新的值。

https://reactjs.org/docs/hooks-reference.html#usestate

const calculationHandler = async () => {
        // async stuff
        setCurrencyResult(previous => {
            return {
                amount: previous.amount,
                currencyFrom: previous.currencyFrom,
                currencyTo: previous.currencyTo,
                multipliedAmount: currencyRate * previous.amount,
                date: Date.now()
            }
        })
    }
}

与 class 组件中的 setState 方法不同,useState 不会自动合并更新对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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