ant Transfer组件,在官网的第一个例子中,点击全选后报警告错误?

版本号:
"antd": "^5.4.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",

这是我的本地代码:

import React, {useEffect, useState} from 'react'
import ReactDOM from 'react-dom/client' //18

import {ConfigProvider, Transfer} from 'antd'

import type {TransferDirection} from 'antd/es/transfer'

interface RecordType {
  key: string
  title: string
  description: string
  chosen: boolean
}

const App = () => {
  const [mockData, setMockData] = useState<RecordType[]>([])
  const [targetKeys, setTargetKeys] = useState<string[]>([])
  const [selectedKeys, setSelectedKeys] = useState<string[]>([])
  const getMock = () => {
    const tempTargetKeys = []
    const tempMockData = []
    for (let i = 0; i < 20; i++) {
      const data = {
        key: i.toString(),
        title: `content${i + 1}`,
        description: `description of content${i + 1}`,
        chosen: i % 2 === 0
      }
      if (data.chosen) {
        tempTargetKeys.push(data.key)
      }
      tempMockData.push(data)
    }
    setMockData(tempMockData)
    setTargetKeys(tempTargetKeys)
  }

  useEffect(() => {
    getMock()
  }, [])

  const handleChange = (
    newTargetKeys: string[],
    direction: TransferDirection,
    moveKeys: string[]
  ) => {
    console.log(newTargetKeys, direction, moveKeys)
    setTargetKeys(newTargetKeys)
  }

  const handleSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
    setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys])
  }

  const renderItem = (item: RecordType) => {
    const customLabel = (
      <span className='custom-item'>
        {item.title} - {item.description}
      </span>
    )

    return {
      label: customLabel, // for displayed item
      value: item.title // for title and filter matching
    }
  }
  return (
    <ConfigProvider>
      <div>
        <Transfer
          dataSource={mockData}
          listStyle={{
            width: 300,
            height: 300
          }}
          selectedKeys={selectedKeys}
          targetKeys={targetKeys}
          onChange={handleChange}
          onSelectChange={handleSelectChange}
          render={renderItem}
        />
      </div>
    </ConfigProvider>
  )
}

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />)

// render(<App />, document.getElementById('root'))

这个是报错截图:

只是把官网的第一个例子用在本地上(直接复制粘贴都没做任何修改),当点击全选按钮的时候就报这个警告错误:在渲染另一个组件(' Transfer ')时无法更新一个组件(' App ')。在' Transfer '中查找错误的setState()调用。
经过我自己测试,发现是 onSelectChange 方法中的 setSelectedKeys 造成的,只要注释这一句就不会报错了;但是这是怎么回事呢??
有没有遇到一样问题的,帮忙看看怎么回事???

阅读 1.2k
1 个回答

你可以用 useSyncExternalStore Hook

import { useSyncExternalStore } from 'use-sync-external-store';

// ...

const App = () => {
  const [mockData, setMockData] = useSyncExternalStore(() => [], []);
  const [targetKeys, setTargetKeys] = useSyncExternalStore(() => [], []);
  const [selectedKeys, setSelectedKeys] = useSyncExternalStore(() => [], []);

  // ...
};
推荐问题
logo
Microsoft
子站问答
访问
宣传栏