当 redux 状态改变时改变 useState

change useState when redux state change

我有一个带有 useState 挂钩的功能组件。它的值来自我的 redux store,我想在每次调度一个动作时用 are store 状态更新状态。

现在我已经硬编码了一个 useState 开头的数组。我希望能够通过 redux 将新元素推送到数组中,并重新呈现新内容。

查看下面的代码:

import React, { useState } from "react";
import "./style.scss";
import { FormEquation } from "../calc/interfaces/form";
import { FlowrateCalc } from "../calc/calculators/FlowrateCalc";
import { useSelector } from "react-redux";
import { RootState } from "../state/reducers";
import { ValveKvsCalc } from "../calc/calculators/ValveKvsCalc";

function Calculator() {
  const state = useSelector((state: RootState) => state.calc);
  
  // const state = [
  //   {
  //     ...FlowrateCalc,
  //     priorityList: FlowrateCalc.inputs.map((input) => input.name),
  //   },
  //   {
  //     ...ValveKvsCalc,
  //     priorityList: ValveKvsCalc.inputs.map((input) => input.name),
  //   },
  // ];

// Usestate is run once after render and never again. How do I update this state whenever new content arrived from "useSelector"??

  const [formsEQ, setformsEQ] = useState<FormEquation[]>([...state]);

  const inputsHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    // Copy form and get index of affected form
    const formCopy = formsEQ.slice();
    const [formName, inputFieldName] = e.target.name.split("-");
    const formIndex = formsEQ.findIndex((formEQ) => formEQ.name === formName);
    if (formIndex === -1) return;
    // if anything other than a number or dot inputted, then return
    // meTODO: if added number then trying to delete all numbers will stop!
    const isInputNum = e.target.value.match(/[0-9]*\.?[0-9]*/);
    if (!isInputNum || isInputNum[0] === "") return;

    // Update priority list to calculate the last updated input
    formCopy[formIndex].priorityList = formCopy[formIndex].priorityList.sort((a, b) => {
      if (a === inputFieldName) return 1;
      if (b === inputFieldName) return -1;
      else return 0;
    });

    // Update selected input field
    formCopy[formIndex].inputs = formCopy[formIndex].inputs.map((input) => {
      if (input.name === inputFieldName) {
        input.value = e.target.value;
      }
      return input;
    });
  
    // If more than two inputs empty do not calculate
    const emptyInputs = formCopy[formIndex].inputs.reduce(
      (acc, nV) => (nV.value === "" ? (acc += 1) : acc),
      0
    );

    // Calculate the last edited input field
    formCopy[formIndex].inputs = formCopy[formIndex].inputs.map((input) => {
      if (input.name === formCopy[formIndex].priorityList[0] && emptyInputs <= 1) {
        const calculatedValue = formCopy[formIndex].calculate(formCopy[formIndex].priorityList[0]);
        input.value = calculatedValue;
      }
      return input;
    });

    // Final set hook, now with calculated value
    setformsEQ([...formCopy]);
  };
  const formInputs = formsEQ.map((formEQ) => {
    return (
      <form className="form" key={formEQ.name}>
        {formEQ.inputs?.map((formInput) => {
          return (
            <div className="form__input" key={formInput.name}>
              <label>{formInput.label}: </label>
              <input
                name={`${formEQ.name}-${formInput.name}`}
                onChange={inputsHandler}
                placeholder={`${formInput.label} (${formInput.selectedUnit})`}
                value={formInput.value}
              />
            </div>
          );
        })}
      </form>
    );
  });

  return <div>{formInputs}</div>;
}

export default Calculator;

对于任何正在阅读本文并且像我一样是 react 新手的人。 我的解决方案是使用 useEffect 钩子;并且每当 useSelector 更新状态常量时,useEffect 钩子将使用 useState set 函数来更新状态。

查看下面添加的解决我的问题的代码:

 useEffect(() => {
    setformsEQ([...state])
 
  }, [state])