我有一个 React 组件,其中多个玩家的输入值应该独立更新。当我切换状态时,第一个输入的值错误地传播到所有其他输入。此外,清除值会在某些输入中留下残留值。我需要帮助解决此同步问题。
这是我当前的代码实现,但问题是当我更改第一个输入的值(如果它有 4 个字母)时,比如说,当我从第一个输入中删除所有字母时,我在所有其他输入中也得到 3 个字母 在所有其他中,始终保留一个数字或字母并不会删除所有
const getFilteredData = (
data: IPlayerTestsResponse[],
categoryId: string
) => {
if (!categoryId) return null;
return data.find((data) => data.player_test_id === categoryId);
};
const getTestResults = (
data: IPlayerTestsResponse[],
categoryId: string,
mode: 'edit' | 'add'
) => {
const result: {
[userId: string]: { target: string; result: string };
} = {};
if (mode === 'edit' && categoryId) {
const filteredData = getFilteredData(data, categoryId);
if (!filteredData) return result;
filteredData.results.forEach(
(resultData) =>
(result[resultData.user_id] = {
target: resultData.target.toString(),
result: resultData.result.toString()
})
);
} else {
players.forEach((player) => {
result[player.user_id] = {
target: '',
result: ''
};
});
}
return result;
};
const [testResults, setTestResults] = useState<{
[userId: string]: {
target: string;
result: string;
};
}>(getTestResults(testResultsData, dropdownInputValue, mode));
useEffect(() => {
if (dropdownInputValue) {
const updatedTestResults = getTestResults(
testResultsData,
dropdownInputValue,
mode
);
setTestResults(updatedTestResults);
} else {
const resetResults = getTestResults(testResultsData, '', 'add');
setTestResults(resetResults);
}
}, [dropdownInputValue, mode, testResultsData]);
const handleTestResultChange = (
userId: string,
type: 'target' | 'result',
value: string
) => {
setTestResults((prevResults) => {
const updatedResults = { ...prevResults };
if (type === 'target' && target) {
const keys = Object.keys(prevResults);
const firstTargetValue = keys.length ? prevResults[keys[0]].target : '';
keys.forEach((key) => {
updatedResults[key] = {
...updatedResults[key],
target: key === userId ? value : firstTargetValue
};
});
} else {
updatedResults[userId] = {
...updatedResults[userId],
[type]: value
};
}
return updatedResults;
});
};
const handleTargetChange = () => {
setTarget((prevTarget) => {
const newTarget = !prevTarget;
setTestResults((prevResults) => {
const updatedResults = { ...prevResults };
if (newTarget) {
const keys = Object.keys(prevResults);
const firstTargetValue = keys.length
? prevResults[keys[0]].target
: '';
keys.forEach((userId) => {
updatedResults[userId] = {
...updatedResults[userId],
target: firstTargetValue
};
});
} else {
Object.keys(prevResults).forEach((userId) => {
updatedResults[userId] = {
...updatedResults[userId],
target: ''
};
});
}
return updatedResults;
});
return newTarget;
});
};
import TestResultTableRow from '../TestResultTableRow/TestResultTableRow';
import './TestResultTable.scss';
type Props = {
players: IPlayer[];
target: boolean;
handleTestResultChange: (
userId: string,
type: 'target' | 'result',
value: string
) => void;
testResults: {
[userId: string]: {
target: string;
result: string;
};
};
};
export default function TestResultTable({
target,
handleTestResultChange,
testResults,
players
}: Props) {
// console.log('Players', players);
// console.log('testResults BEFORE MAP', testResults);
let counter = 0;
return (
<div className="test-result-table">
<>
<TestResultTableRow gridColumns={3}>
<div className="test-result-table__name">PLAYER</div>
<div className="test-result-table__target">TARGET</div>
<div className="test-result-table__target">RESULT</div>
</TestResultTableRow>
</>
<div className="test-result-table__body">
{players.map((player, index) => {
counter++;
console.log(index, counter);
return (
<TestResultTableRow key={player.user_id} gridColumns={3}>
<div className="test-result-table__body__name">{`${player.firstname} ${player.lastname}`}</div>
<input
className={`test-result-table__body__target ${target && index !== 0 ? ' test-result-table__body__target--filled' : ''}`}
name="target[]"
type="text"
value={testResults[player.user_id]?.target || ''}
onChange={(e) =>
handleTestResultChange(
player.user_id,
'target',
e.target.value
)
}
disabled={target && index !== 0}
/>
<input
className="test-result-table__body__target "
type="text"
value={testResults[player.user_id]?.result || ''}
onChange={(e) =>
handleTestResultChange(
player.user_id,
'result',
e.target.value
)
}
/>
</TestResultTableRow>
);
})}
</div>
</div>
);
}
我认为按索引更新将是更新状态的最佳选择,下面添加了一个示例,请检查,这可能对您有帮助。 请检查handleChange功能
import { useState } from 'react';
export default function PageLanding() {
const [players, setPlayers] = useState([
{
player: 'John',
target: 0,
result: 1,
},
{
player: 'Doe',
target: 0,
result: 2,
},
{
player: 'Sam',
target: 0,
result: 3,
},
]);
// Update players by Index
const handleChange = (value, index) => {
var oldValue = [...players];
oldValue[index].target = value;
setPlayers(oldValue);
};
return (
<>
<table>
<thead>
<tr>
<td>Player</td>
<td>Target</td>
<td>Result</td>
</tr>
</thead>
<tbody>
{players.map((player, index) => (
<tr key={index}>
<td>{player.player}</td>
<td>
<input
type="text"
value={player.target}
onChange={(e) => handleChange(e.target.value, index)}
/>
</td>
<td>{player.result * player.target}</td>
</tr>
))}
</tbody>
</table>
</>
);
}