ReactJS: useReducer分派两个不同的动作,而不是一个



我正在尝试构建一个排序算法可视化器,该可视化器在单击按钮时每秒对包含整数的数组的元素进行排序。每当我点击"选择排序"时按钮,但是,它会调度随机化;首先是动作类型,然后是选择排序。如果它仍然对数组进行排序,这是可以的,但它没有,而是使用了"选择排序"。按钮在功能上充当第二个"随机化"按钮。按钮。我是否错误地使用了useReducer钩子?我怎样才能使它只分派一个动作类型呢?

arr-context-provider.tsx

import { createContext, useReducer } from "react";
import ControlPanel from './components/control-panel';
import Visualizer from './components/visualizer';
interface ArrayContextProps {
children: React.ReactElement;
}
export type Action = 
| { type: "selection sort" }
| { type: "randomize" }
const initArr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
export const arrContext = createContext<[number[], React.Dispatch<Action>]>([initArr, () => initArr]);
const ArrContextProvider: React.FC<ArrayContextProps> = ({ children }: ArrayContextProps) => {
const arrReducer = (arr: number[], action: Action) => {
switch (action.type) {
case "selection sort":
for (let i = 0; i < arr.length; i++) {
setTimeout(() => {
let minIndex = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex !== i) {
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}

console.log("selection sort!");
return [...arr.slice()];
}, 100 * (i + 1));
}

case "randomize":
arr = [];
while (arr.length < 10) {
let rng = Math.floor(Math.random() * 10) + 1;
if (arr.indexOf(rng) === -1) {
arr.push(rng);
}
}
console.log("randomize!");
return [...arr.slice()];

default:
console.log("error!");
return [...arr.slice()];
}
}
const [arr, dispatch] = useReducer<(arr: number[], action: Action) => number[]>(arrReducer, initArr);
return (
<arrContext.Provider value={[arr, dispatch]}>
<div>
<ControlPanel />
<Visualizer />
</div>
</arrContext.Provider>
);
};
export default ArrContextProvider;

control-panel.tsx

import { useState, useEffect, useContext } from 'react';
import { arrContext, Action } from './arr-context-provider';
const ControlPanel: React.FC = () => {
const [arr, dispatch] = useContext<[number[], React.Dispatch<Action>]>(arrContext);
const [algorithm, setAlgorithm] = useState("");
useEffect(() => {
switch(algorithm) {
case "selection sort":
dispatch({ type: "selection sort" });
case "randomize":
dispatch({ type: "randomize" });
setAlgorithm("");
default:
[...arr.slice()];
}
}, [algorithm]);
return (
<div className='headerContainer'>
<h1 className='header'>🆂🅾🆁🆃🅸🅽🅶 🅰🅻🅶🅾🆁🅸🆃🅷🅼 🆅🅸🆂🆄🅰🅻🅸🆉🅴🆁</h1>
<li className='list'>
<ul><button className='button' onClick={() => setAlgorithm("selection sort")}>Selection Sort</button></ul>
<ul><button className='button' onClick={() => setAlgorithm("randomize")}>Randomize</button></ul>
</li>
</div>
)
}

export default ControlPanel;

我不确定你在这里是否正确使用了useContext:

const [arr, dispatch] = useContext<[number[], React.Dispatch<Action>]>(arrContext);

dispatch函数应该来自useReducer而不是useContext。

来自文档:

import { useContext } from 'react';
function MyComponent() {
const theme = useContext(ThemeContext);
// ...

import { useReducer } from 'react';
function reducer(state, action) {
// ...
}
function MyComponent() {
const [state, dispatch] = useReducer(reducer, { age: 42 });
// ...

您的代码在switch-case语句中有问题。在每种情况之后使用break或return语句。如果你不这样做,下一个案子也会运行。你不应该在reducer中使用setTimeout。只需从reducer返回状态,然后以不同的方式处理UI。

case "selection sort":
...your code,
break;

相关内容

  • 没有找到相关文章

最新更新