reactjs 如何将JavaScript item comparator脚本转换为React应用程序?

wwwo4jvm  于 2023-05-06  发布在  React
关注(0)|答案(1)|浏览(149)

我写了一个JavaScript脚本,它模拟了一个“项目比较器”,用户可以通过一系列用户输入创建一个排名列表。
我正在尝试构建一个简单的React应用程序,将此逻辑转换为用户界面。然而,由于我是React的新手,我很难获得一个功能正常的应用程序,我担心我没有使用正确的方法。任何帮助将不胜感激。
下面是包含我试图复制的逻辑的JavaScript代码:

const readline = require('readline-sync');

const items = ["A", "B", "C", "D", "E"];

let rankedListCount = 1;

// For each item, use a binary search approach to determine its spot in the list
for (let i = 1; i < items.length; i++) {
  const item = items[i];
  console.log(`Comparing ${item} to the existing list...`);
  
  let left = 0;
  let right = i - 1;
  
  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    const comparison_item = items[mid];
    const preference = readline.question(`Do you prefer ${item} or ${comparison_item}? Enter 1 or 2: `);
    
    if (preference === "1") {
      right = mid - 1;
    } else {
      left = mid + 1;
    }
  }
  
  const index = left;
  items.splice(i, 1);
  items.splice(index, 0, item);
  rankedListCount++;

  console.log(`Inserted ${item} at position ${index}\n`);
  console.log("Your current ranking of the items is:");
for (let i = 0; i < rankedListCount; i++) {
  console.log(`${i+1}) ${items[i]}`);
}
}

console.log("Your final ranking of the items is:");
for (let i = 0; i < items.length; i++) {
  console.log(`${i+1}) ${items[i]}`);
}

这是我的React代码的当前状态。我希望用户能够按下按钮来完成比较,并有真实的更新的排名列表。
首先,我的选项是“选择哪个项目更好:”,有按钮说B和A和排名列表A-E。如果我点击其中一个按钮,什么也不会发生。
如果我再次单击它,按钮的内容会消失,排名列表也会消失。

import React, { useEffect, useState } from 'react';

const ItemComparator = () => {
  const [rankedItemList, setRankedItemList] = useState(['A', 'B', 'C', 'D', 'E']);
  const [rankedItemsCount, setRankedItemsCount] = useState(1);
  const [primaryItem, setPrimaryItem] = useState(rankedItemList[1]);
  const [comparisonItem, setComparisonItem] = useState(rankedItemList[0]);
  const [leftIndex, setLeftIndex] = useState(0);
  const [rightIndex, setRightIndex] = useState(rankedItemsCount-1);
  const [midIndex, setMidIndex] = useState(Math.floor((leftIndex + rightIndex) / 2));

  function handleSelection(preferredItem) {
    if (preferredItem === 'primary') {
      setRightIndex(midIndex-1);
    } else {
      setLeftIndex(midIndex+1);
    }

    if (leftIndex > rightIndex) {
      setRankedItemList(rankedItemList.splice(rankedItemsCount, 1));
      setRankedItemList(rankedItemList.splice(leftIndex, 0, primaryItem));
      setRankedItemsCount(rankedItemsCount+1);
      setPrimaryItem(rankedItemList[rankedItemsCount]);
      setLeftIndex(0);
      setRightIndex(rankedItemsCount-1);
      setMidIndex(Math.floor((leftIndex + rightIndex) / 2));
      setComparisonItem(rankedItemList[midIndex]);
    }
  }

  return (
    <div>
      <h1>Item Comparator</h1>
      <p>Select which item is better:</p>
      <div>
        <button onClick={() => handleSelection('primary')}>{rankedItemList[rankedItemsCount]}</button>
        <button onClick={() => handleSelection('comparison')}>{rankedItemList[midIndex]}</button>
      </div>
      <h2>Comparison List</h2>
      <ol>
        <li>{rankedItemList[0]}</li>
        <li>{rankedItemList[1]}</li>
        <li>{rankedItemList[2]}</li>
        <li>{rankedItemList[3]}</li>
        <li>{rankedItemList[4]}</li>
      </ol>
    </div>
  );
}

export default ItemComparator;
11dmarpk

11dmarpk1#

您可能误解了useState的工作原理。你不能仅仅把它作为一个参考值。
每次调用状态设置器(例如setRankedItemList)时,都在更新react状态。
通过调用

setRankedItemList(rankedItemList.splice(rankedItemsCount, 1));
setRankedItemList(rankedItemList.splice(leftIndex, 0, primaryItem));

您将覆盖rankedItemList状态两次。React是“聪明的”,可以捆绑状态更新以提高性能,这就是为什么你会看到一些奇怪的行为。
为了获得你期望的行为,你可以在handleSelection方法中使用本地或引用值。
例如,leftIndexrightIndex可以是一个常数,每次调用handleSelection方法时都会计算出来,如下所示:

function handleSelection(preferredItem) {
  let leftIndex = 0;
  let rightIndex = rankedItemsCount - 1;

  if (preferredItem === "primary") {
    rightIndex = midIndex - 1
  } else {
    leftIndex = midIndex + 1
  }

  // ...rest
}

此外,在再次更新状态之前,应计算一次新的排名项

function handleSelection(preferredItem) {
  // ...calculating indexes
  
  const newRankedItems = []

  // ... your logic to set the newRankedItems

  setRankedItemList(newRankedItems) // Just a single call to update the state
}

另外,您处理显示rankedItemList的方式与您在react中执行此操作的方式不同,请查看the docs

相关问题