DetailsList 正在重新呈现,因此正在失去其状态
DetailsList is getting re-rendered and hence is loosing its state
所以我一直在努力实现这样的想法,即每当用户单击 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 并一直在敲我的头,但问题仍然存在,点击任何行状态丢失并且按钮未启用。我已经尝试过存储选择状态,计数,一切,但似乎我错过了实施的必要或基础的东西
您需要记住 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();
},[])
The final code sample 应该是这样的:
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;
接受的答案对问题有正确的推理。我也想 post 我的解决方案。我只需要存储项目的状态
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 并将依赖项设置为该源
所以我一直在努力实现这样的想法,即每当用户单击 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 并一直在敲我的头,但问题仍然存在,点击任何行状态丢失并且按钮未启用。我已经尝试过存储选择状态,计数,一切,但似乎我错过了实施的必要或基础的东西
您需要记住 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();
},[])
The final code sample 应该是这样的:
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;
接受的答案对问题有正确的推理。我也想 post 我的解决方案。我只需要存储项目的状态
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 并将依赖项设置为该源