0

因此,我一直在尝试实现这样的想法,即每当用户单击 DetailsList 中的任何行时,按钮都会启用,而当用户在选择区域之外单击时,按钮会被禁用。

这是我的代码

import { DetailsList, SelectionMode, Selection, ISelection, initializeIcons, PrimaryButton } from '@fluentui/react'
import {useMemo } from 'react'
import { useBoolean } from '@uifabric/react-hooks'

interface ICurrency {
  type: string,
  amount: number
}
function App() {

  initializeIcons()
  const [isBtn, { setTrue: disableBtn, setFalse: enableBtn }] = useBoolean(true)
  const items: ICurrency[] = [
    {
      type: 'INR',
      amount: 20
    },
    {
      type: 'USD',
      amount: 50
    },
    {
      type: 'GBP',
      amount: 70
    }
  ]



  const selection: ISelection = useMemo(() => new Selection(
    {
      onSelectionChanged: ()=>{
        if(selection.getSelectedCount() > 0){
          enableBtn()
        }else{
          disableBtn()
        }
      }
    }
  ), [items])


  return (
    <div className="App">
      <PrimaryButton text="Button" disabled={isBtn}/>
      <DetailsList
        items={items} selectionMode={SelectionMode.single}
        selection={selection}
      />
    </div>
  );
}

export default App;

我什至使用了 useMemo 并继续敲打我的头,但问题仍然存在,单击任何行,状态丢失并且按钮未启用。我已经尝试过存储选择状态,计数,一切,但似乎我错过了一些对实施至关重要或基本的东西

4

2 回答 2

1

您需要记住,items因为在每次渲染时都会重新分配它并考虑一个新数组,这会导致您selection发生更改,因为它依赖于items依赖项useMemo。在每次状态更新时,选择都会重置。

因此,解决此问题的一种方法是将项目移出函数,使其保持引用,而不是在每次渲染时创建新的项目数组。

const items = [
  {
    type: "INR",
    amount: 20
  },
  {
    type: "USD",
    amount: 50
  },
  {
    type: "GBP",
    amount: 70
  }
];

function App() {
  // code
}

或通过useMemo在这些项目上使用:

const items = useMemo(() =>  [
  {
    type: "INR",
    amount: 20
  },
  {
    type: "USD",
    amount: 50
  },
  {
    type: "GBP",
    amount: 70
  }
],[]);

我也看到你有一个错误,initializeIcons应该只调用一次。所以这可能应该放在useEffect

useEffect(() => {
  initializeIcons();
},[])

最终的代码示例应如下所示:

import {
  DetailsList,
  SelectionMode,
  Selection,
  ISelection,
  initializeIcons,
  PrimaryButton
} from "@fluentui/react";
import { useMemo, useEffect } from "react";
import { useBoolean } from "@uifabric/react-hooks";

const items = [
  {
    type: "INR",
    amount: 20
  },
  {
    type: "USD",
    amount: 50
  },
  {
    type: "GBP",
    amount: 70
  }
];

function App() {
  useEffect(() => {
    initializeIcons();
  }, []);

  const [isBtn, { setTrue: disableBtn, setFalse: enableBtn }] = useBoolean(
    true
  );

  const selection = useMemo(
    () =>
      new Selection({
        onSelectionChanged: () => {
          if (selection.getSelectedCount() > 0) {
            enableBtn();
          } else {
            disableBtn();
          }
        }
      }),
    [items]
  );

  return (
    <div className="App">
      <PrimaryButton text="Button" disabled={isBtn} />
      <DetailsList
        items={items}
        selectionMode={SelectionMode.single}
        selection={selection}
      />
    </div>
  );
}

export default App;

于 2021-02-26T02:17:39.477 回答
1

接受的答案对问题有正确的推理。我也只是想发布我的解决方案。我只需要存储项目的状态

import { DetailsList, SelectionMode, Selection, initializeIcons, PrimaryButton } from '@fluentui/react'
import { useEffect, useState } from 'react'
import { useBoolean } from '@uifabric/react-hooks'

interface ICurrency {
    type: string,
    amount: number
}

function App() {

    useEffect(() => {
        initializeIcons();
    }, []);

    const [isBtn, { setTrue: disableBtn, setFalse: enableBtn }] = useBoolean(true)

    let _selection = new Selection({
        onSelectionChanged: () => {
            if (_selection.getSelectedCount() > 0) {
                enableBtn()
            } else {
                disableBtn()
            }
        }
    });

    let _initialItems: ICurrency[] = [
        {
            type: 'INR',
            amount: 20
        },
        {
            type: 'USD',
            amount: 50
        },
        {
            type: 'GBP',
            amount: 70
        }
    ]

    const [items, setItems] = useState(_initialItems)

    return (
        <>
            <PrimaryButton text="Button" disabled={isBtn} />
            <DetailsList
                items={items}
                selection={_selection}
                selectionMode={SelectionMode.single}
            />
        </>
    );
}

export default App;

现在说如果项目来自某些道具或某些状态管理,那么只需在 useEffect 中使用 setItems 并将依赖项设置为该源

于 2021-02-26T02:57:17.897 回答