簡體   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