我正在使用 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;
我不明白为什么该字符串可以正常工作,但其他两个却不能。如有任何帮助,我们将不胜感激!
这里的问题是排队的 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
})
);
}
});