单击时按钮不移动(函数 moveButton)

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

在下面的代码中,当我单击按钮时,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 结构,但没有帮助。

reactjs button onclick right-mouse-button
1个回答
0
投票

问题似乎可能与您更新状态的方式有关。在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 函数中的右键单击行为。

希望这对您有帮助。

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