将数组添加到redux存储中,但它只获取数组项的原始状态

问题描述 投票:0回答:1

我正在使用 React 和 Redux 开发一个应用程序的 2 个页面。在第一页上,您输入一个字符串,它会反向显示该字符串并告诉您它是否是回文。一旦提交了一个字符串,它就会被添加到 redux 存储中。在第二页上,它显示输入的字符串及其反向对应字符串的列表,如果是回文,则会显示标记为 P 的徽章。

原始字符串按预期显示在第二页上。然而,反转的字符串和回文徽章仅显示其原始状态。

我使用 console.log 查看发送到商店的数组的值是什么,后两项没有更新。例如,当我输入字符串“Hello There”时,添加到存储中的数组应该是 {originalString: 'Hello There', returnedString: 'erehT olleH', isPalindrome: false}。相反,我得到了 {originalString: 'Hello There', returnedString: '', isPalindrome: true}

这是第一页的代码:

import React, { useState } from "react";
import { useFormik } from "formik";
import { useDispatch } from "react-redux";
import { addStringResult } from "../../redux/reverseStringSlice";

export const ReverseString = () => {
  /**
   * Hooks
   */
  const [string, setString] = useState("");
  const [reverseString, setReverseString] = useState("");
  const [inputClass, setInputClass] = useState("form-control");
  const [isButtonDisabled, setButtonDisabled] = useState(true);
  const [isChecked, setIsChecked] = useState(false);
  const [isHiddenYes, setIsHiddenYes] = useState(true);
  const [isHiddenNo, setIsHiddenNo] = useState(true);
  const dispatch = useDispatch();

  const validate = () => {
    const errors = {};

    if (string.length < 1) {
      errors.string = "An original string is required";
      setInputClass("form-control is-invalid");
    }

    return errors;
  };

  /**
   * Javascript Code
   */

  const formik = useFormik({
    initialValues: {},
    validate,
    onSubmit: () => {
      let reverseArray = [...string];
      reverseArray.reverse();
      let newArray = reverseArray.join("");
      setReverseString(newArray);
      setButtonDisabled(false);
      setInputClass("form-control");
      if (
        isChecked === true &&
        string.length > 0 &&
        string.replace(/ /g, "").toLowerCase() ===
          string.replace(/ /g, "").toLowerCase().split("").reverse().join("")
      ) {
        setIsHiddenYes(false);
        setIsHiddenNo(true);
      } else if (isChecked === true && string.length > 0) {
        setIsHiddenNo(false);
        setIsHiddenYes(true);
      }
      dispatch(
        addStringResult({
          originalString: string,
          reversedString: reverseString,
          isPalindrome: isHiddenNo,
        })
      );
    },
  });

  const clearAll = () => {
    setString("");
    setReverseString("");
    setInputClass("form-control");
    setButtonDisabled(true);
    setIsChecked(false);
    setIsHiddenYes(true);
    setIsHiddenNo(true);
  };
  /**
   * HTML Code (JSX)
   */
  return (
    <form onSubmit={formik.handleSubmit}>
      <div>
        <label htmlFor="reverseString" className="form-label">
          <h1>Reverse String</h1>
        </label>
      </div>
      <div className="input-group input-group-lg mb-1 has-validation">
        <span className="input-group-text" id="originalStringAddOn">
          Original String
        </span>
        <input
          type="text"
          className={inputClass}
          id="string"
          value={string}
          onChange={(e) => setString(e.target.value)}
        />
        <div className="invalid-feedback">{formik.errors.string}</div>
      </div>
      <div className="input-group input-group-lg mb-2">
        <span className="input-group-text" id="reverseStringAddOn">
          Reversed String
        </span>
        <input
          type="text"
          className="form-control"
          id="reverseString"
          value={reverseString}
          onChange={(e) => setReverseString(e.target.value)}
          readOnly
        />
      </div>
      <div className="form-check">
        <input
          className="form-check-input"
          type="checkbox"
          value=""
          id="palindromeCheckBox"
          checked={isChecked}
          onChange={() => setIsChecked((prev) => !prev)}
        />
        <label className="form-check-label" htmlFor="palindromeCheckBox">
          Is the Original String a palindrome?
        </label>
      </div>
      <div
        className="alert alert-primary"
        role="alert"
        id="alertYes"
        hidden={isHiddenYes}
      >
        Yes the original string of {string} is a palindrome.
      </div>
      <div
        className="alert alert-danger"
        role="alert"
        id="alertNo"
        hidden={isHiddenNo}
      >
        No, the original string of {string} is not a palindrome.
      </div>
      <div>
        <button className="btn btn-primary" type="submit">
          Display
        </button>{" "}
        <button
          className="btn btn-danger"
          onClick={clearAll}
          disabled={isButtonDisabled}
        >
          Clear
        </button>
      </div>
    </form>
  );
};

这是第二页的代码:

import React from "react";
import { StringResult } from "../StringResult/StringResult";
import { selectStringResults } from "../../redux/reverseStringSlice";
import { useSelector } from "react-redux";

export const ReverseStringResults = () => {
  const stringResults = useSelector(selectStringResults);
console.log(stringResults)
  return (
    <div>
      <h1>Reverse String Results</h1>
      <ol className="list-group list-group-numbered">
        {stringResults.map((stringResult) => {
          return (
            <StringResult
              key={stringResult.originalString}
              stringResult={stringResult}
            />
          );
        })}
      </ol>
    </div>
  );
};

这是 redux 切片的代码

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  stringResults: [
    {
      originalString: "Hello World",
      reversedString: "dlroW olleH",
      isPalindrome: false,
    },
    {
      originalString: "kayak",
      reversedString: "kayak",
      isPalindrome: true,
    },
    {
      originalString: "my gym",
      reversedString: "myg ym",
      isPalindrome: true,
    },
    {
      originalString: "Love React",
      reversedString: "tcaeR evoL",
      isPalindrome: false,
    },
    {
      originalString: "mom",
      reversedString: "mom",
      isPalindrome: true,
    },
  ],
};

export const reverseStringSlice = createSlice({
  name: "stringResults",
  initialState,
  reducers: {
    addStringResult: (state, action) => {
      return {
        ...state,
        stringResults: [
          ...state.stringResults,
          {
            originalString: action.payload.originalString,
            reversedString: action.payload.reversedString,
            isPalindrome: action.payload.isPalindrome,
          },
        ],
      };
    },
  },
});

export const { addStringResult } = reverseStringSlice.actions;
export const selectStringResults = (state) => state.stringResults.stringResults;

export default reverseStringSlice.reducer;

我不明白为什么该字符串可以正常工作,但其他两个却不能。如有任何帮助,我们将不胜感激!

arrays react-redux redux-toolkit data-retrieval storing-data
1个回答
0
投票

问题

这里的问题是排队的 React 状态更新不会立即处理。在表单的提交处理程序中更新的

reverseString
isHiddenNo
值是对 unupdated
reverseString
isHiddenNo
状态的过时闭包,陈旧/过时的值将被分派到商店。

解决方案

计算反转的字符串值,如果该字符串是提交处理程序中的回文,并在分派到商店时使用这些计算值。

const formik = useFormik({
  initialValues: {},
  validate,
  onSubmit: () => {
    const reversedString = string.split("").toReversed().join("");
    const isPalindrome =
      string.replace(/ /g, "").toLowerCase() ===
      reversedString.replace(/ /g, "").toLowerCase();

    setReverseString(reversedString);
    setButtonDisabled(false);
    setInputClass("form-control");

    if (isChecked && string.length) {
      setIsHiddenYes(!isPalindrome);
      setIsHiddenNo(isPalindrome);
    }

    dispatch(
      addStringResult({
        originalString: string,
        reversedString,
        isPalindrome
      })
    );
  }
});

Edit adding-array-to-redux-store-but-its-only-taking-the-original-state-of-the-arra

© www.soinside.com 2019 - 2024. All rights reserved.