【问题标题】:React functional component, useState call back without using useEffectReact 功能组件,useState 回调不使用 useEffect
【发布时间】:2021-02-28 06:24:27
【问题描述】:

我对 reactJS 很陌生,可能有过于复杂的事情或没有正确计划。

我在使用 useState 挂钩来跟踪项目中的属性时遇到了问题。

好的,那就这样吧

  1. 由于使用了react-hook-form,value 取自输入文本框作为类型文本
  2. 然后检查type,看它是否等于“收入”或“费用”
  3. 如果type == "income" 则只需使用setValue 设置value 而不做任何更改,否则如果type == "expense" 然后*=-1 并设置value 使用setValue
  4. parseInt() 与 setValue 一起使用,以确保将值保存为数字
  5. 调用setRecords 将相关信息添加到record 对象数组中。

从上面的 5 个步骤可以看出,useState 钩子 setValue 和 setRecords 被一个接一个地调用,我目前遇到的问题是在应用程序的初始运行时, value 将追加而不是添加。

据我了解,因为 useState 钩子是异步的,不会立即返回结果,所以在调用 setRecords 时,value 仍然是文本类型而不是数字

我在网上搜索了一段时间,但找不到解决此问题的好方法,不使用 useEffect 钩子,我尝试使用 useEffect 钩子,但我没有设法让它工作,允许用户输入相同的value,应用仍应将该值附加到record 对象数组中。

最后,我决定新建一个属性currentValue,并在表单提交时设置它,因为这不是状态,会立即更新,不必等待setValue更新@ 987654344@状态。

有没有更好的方法来解决这个问题?或者解决方法可以吗?

import React, { useEffect, useContext } from "react";
import RecordList from "./RecordList";
import { useForm } from "react-hook-form";
import { BudgetPlannerContext } from "../context/BudgetPlannerContext";

const BudgetPlanner = () => {
  const { register, handleSubmit, errors } = useForm();
  const [
    records,
    setRecords,
    total,
    setTotal,
    type,
    setType,
    value,
    setValue,
    description,
    setDescription,
  ] = useContext(BudgetPlannerContext);

  let currentValue = 0;

  useEffect(() => {
    setTotal(() =>
      records.reduce((acc, curr) => {
        return acc + curr.value;
      }, 0)
    );
  }, [records, setTotal]);

  const onFormSubmit = (data) => {
    if ((type === "Income") & (data.value !== 0)) {
      currentValue = parseInt(data.value);
      setValue(parseInt(data.value));
    } else if ((type === "Expense") & (data.value !== 0)) {
      currentValue = parseInt((data.value *= -1));
      setValue(parseInt((data.value *= -1)));
    } else {
      return null;
    }
    setDescription(data.description);
    processValue(type, currentValue);
  };

  const processValue = (type, currentValue) => {
    updateRecord(type, currentValue);
    //setValue(0);
    //setDescription("");
    //console.log(records);
  };

  const updateRecord = (type, currentValue) => {
    setRecords((oldRecord) => [
      ...oldRecord,
      {
        type: type,
        value: currentValue,
        description: description,
        id: Math.random() * 1000,
      },
    ]);
  };

  return (
    <div className="ui segment">
      <div className="search-bar ui segment">
        <form className="ui form" onSubmit={handleSubmit(onFormSubmit)}>
          <div className="field">
            <select
              onChange={(e) => setType(e.target.value)}
              name="todos"
              ref={register}
              className="filter-todo"
            >
              <option value="" defaultValue="defaultValue">
                ---
              </option>
              <option value="Income">Income</option>
              <option value="Expense">Expense</option>
            </select>
            <input
              name="description"
              type="text"
              placeholder="Description"
              ref={register}
            />
            <input
              name="value"
              type="number"
              placeholder="Value"
              ref={register}
            />
          </div>
          <div>Total: {total}</div>
          <button type="submit">Submit</button>
        </form>
      </div>
      <RecordList records={records} setRecords={setRecords} />
    </div>
  );
};

export default BudgetPlanner;

【问题讨论】:

    标签: reactjs react-hooks use-effect use-state asynccallback


    【解决方案1】:

    如果我是你,我只会将新值作为参数传递给你正在调用的其他函数:

    const onFormSubmit = (data) => {
        if (data.value === 0 || (type !== 'Income' && type !== 'Expense')) {
            return;
        }
        const newValue = parseInt(data.value) * (type === 'Income' ? 1 : -1);
        setValue(newValue);
        setDescription(data.description);
        processValue(type, newValue);
    };
    

    不需要额外的外部变量。

    另一种选择是使用useEffect(或者,最好是useLayoutEffect)并在value 更改时调用processValue:

    const onFormSubmit = (data) => {
        if (data.value === 0 || (type !== 'Income' && type !== 'Expense')) {
            return;
        }
        const newValue = parseInt(data.value) * (type === 'Income' ? 1 : -1);
        setValue(newValue);
        setDescription(data.description);
    };
    useLayoutEffect(() => {
        if (value) {
            processValue(type);
        }
    }, [value]);
    

    并让processValue 使用外部value 有状态变量。

    【讨论】:

    • 感谢您的快速响应,我已经采纳了您对onFormSubmit 函数的第一个建议,并对我的代码进行了更改,现在看起来好多了。
    猜你喜欢
    • 2021-05-22
    • 2021-11-26
    • 2019-12-03
    • 2020-01-06
    • 2021-02-17
    • 2021-04-03
    • 1970-01-01
    • 2020-12-04
    • 2020-06-10
    相关资源
    最近更新 更多