在下面的代码中,当我单击按钮时,buttonsColumns 状态会按预期更新(如 moveButton 函数中的 console.log 所示),因此,按钮应立即向右或向左移动,具体取决于是否我用鼠标右键或左键单击它们。但是,只有当我单击输入字段并输入内容时,页面上显示的位置才会更新。我不明白为什么它会这样。有什么想法可以帮助我吗?
此外,我还根据单击鼠标右键还是左键来计划了两种不同的行为。我设法捕获正常(左)单击(如 console.log 所示),但无法捕获右键单击。你能告诉我为什么以及如何解决这个问题吗?
const AssemblyLine = props => {
let columns = {}
for (let stage of props.stages) {
columns[stage] = []
}
const [buttonsColumns, setButtonsColumns] = useState (columns)
const [newInput, setNewInput] = useState("")
const buttons = (stage) => {
const allButtons = buttonsColumns[stage].map ((input) => {
return (
<button
data-testid="assembly-item"
key = {input}
onClick = {(e) => moveButton(e, stage, input)}
>
{input}
</button>
)
})
return allButtons
}
const stages = props.stages.map ((stage, index) => {
return (
<div
data-testid="stage"
key = {index} >
<span> {stage} </span>
{buttons(stage)}
</div>
)
})
function addNewButton () {
let updatedObject = buttonsColumns
updatedObject[props.stages[0]].unshift(newInput)
setButtonsColumns (updatedObject)
setNewInput("")
}
function moveButton (e, stage, input) {
let updatedObject = buttonsColumns
updatedObject[stage]= updatedObject[stage].filter( x => x !== input)
if (e.button===0) {
console.log("clic gauche")
let positionForward = props.stages.indexOf(stage)+1
if (positionForward<props.stages.length) {
updatedObject[props.stages[positionForward]].unshift(input)
}
}
if (e.button===2) {
console.log("clic droit")
let positionBackward = props.stages.indexOf(stage)-1
if (positionBackward>0){
updatedObject[props.stages[positionBackward]].push(input)
}
}
setButtonsColumns (updatedObject)
console.log("resultat", buttonsColumns)
}
return (
<>
<input
name = "newButton"
data-testid = "add-item"
onKeyDown = {e => e.key === "Enter" ? addNewButton() : null}
onChange = {e => setNewInput(e.target.value)}
value = {newInput}
/>
<div id="stagesContainer">
{stages}
</div>
</>
);
};
export default AssemblyLine;
这是在 app.js 中传递的 props.stages 的示例:
"Idea",
"Development",
"Testing",
"Deployment"
]
我删除了if条件,但是没有用。我还尝试编辑 columnsButtons 结构,但没有帮助。
问题似乎可能与您更新状态的方式有关。在React中,当你使用useState钩子来管理状态时,你应该避免直接修改状态变量。相反,创建状态的副本,然后更新该副本。这可以确保 React 正确检测到状态变化。
我已经更新了 moveButton 和 addNewButton 函数以使用正确的方法:
import React, { useState } from 'react';
const AssemblyLine = (props) => {
let columns = {};
for (let stage of props.stages) {
columns[stage] = [];
}
const [buttonsColumns, setButtonsColumns] = useState(columns);
const [newInput, setNewInput] = useState('');
const buttons = (stage) => {
const allButtons = buttonsColumns[stage].map((input) => {
return (
<button
data-testid="assembly-item"
key={input}
onClick={(e) => moveButton(e, stage, input)}
onContextMenu={(e) => handleContextMenu(e, stage, input)}
>
{input}
</button>
);
});
return allButtons;
};
const stages = props.stages.map((stage, index) => {
return (
<div data-testid="stage" key={index}>
<span> {stage} </span>
{buttons(stage)}
</div>
);
});
function addNewButton() {
const updatedObject = { ...buttonsColumns };
updatedObject[props.stages[0]].unshift(newInput);
setButtonsColumns(updatedObject);
setNewInput('');
}
function moveButton(e, stage, input) {
e.preventDefault(); // Prevent the default behavior for left-click
const updatedObject = { ...buttonsColumns };
updatedObject[stage] = updatedObject[stage].filter((x) => x !== input);
if (e.button === 0) {
console.log('Left click');
const positionForward = props.stages.indexOf(stage) + 1;
if (positionForward < props.stages.length) {
updatedObject[props.stages[positionForward]].unshift(input);
}
}
setButtonsColumns(updatedObject);
console.log('Result:', buttonsColumns);
}
function handleContextMenu(e, stage, input) {
e.preventDefault(); // Prevent the default context menu for right-click
console.log('Right click');
const updatedObject = { ...buttonsColumns };
const positionBackward = props.stages.indexOf(stage) - 1;
if (positionBackward >= 0) {
updatedObject[props.stages[positionBackward]].push(input);
}
setButtonsColumns(updatedObject);
console.log('Result:', buttonsColumns);
}
return (
<>
<input
name="newButton"
data-testid="add-item"
onKeyDown={(e) => (e.key === 'Enter' ? addNewButton() : null)}
onChange={(e) => setNewInput(e.target.value)}
value={newInput}
/>
<div id="stagesContainer">{stages}</div>
</>
);
};
export default AssemblyLine;
而且,我还为按钮添加了 onContextMenu 事件,以捕获右键单击并阻止默认上下文菜单。这允许您处理 moveButton 函数中的右键单击行为。
希望这对您有帮助。