提问人:Gaurav Rajput 提问时间:11/12/2023 更新时间:11/12/2023 访问量:39
为什么在不同组件中渲染列表不适用于材质UI提供的“选择”组件?
Why does Rendering the List in a Different component doesn't work with `Select` Component provided by material UI?
问:
我写了两个组件。一个用于渲染列表,该列表在其托管 Material UI 提供的组件的父组件中使用。
两者的片段如下。Select
import React from 'react';
import './index.css';
import { LMFeedTopics } from '@likeminds.community/feed-js-beta';
import { Checkbox, MenuItem } from '@mui/material';
interface TopicListProps {
list: LMFeedTopics[];
checkedList: string[];
}
const TopicList = ({ list, checkedList }: TopicListProps) => {
return (
<>
{list.map((topic: LMFeedTopics) => {
return (
<MenuItem key={topic.Id} value={topic.Id} role="option">
<div className="topicTile">
<Checkbox checked={checkedList.includes(topic.Id)} />
<span>{topic.name}</span>
</div>
</MenuItem>
);
})}
</>
);
};
export default TopicList;
Parent 组件是
import React, { useCallback, useEffect, useState } from 'react';
import './index.css';
import { LMFeedTopics } from '@likeminds.community/feed-js-beta';
import { lmFeedClient } from '../../..';
import { Checkbox, FormControl, MenuItem, Select } from '@mui/material';
import TopicList from '../topic-list';
interface TopicFeedDropdownSelectorProps {}
const TopicFeedDropdownSelector = () => {
const [topicList, setTopicList] = useState<any[]>([]);
const [checkedTopicList, setCheckedTopicList] = useState<string[]>([]);
const [page, setPage] = useState<number>(1);
const [searchKey, setSearchKey] = useState<string>('');
const getData = useCallback(async () => {
// Used go get some data with an API call.
}, [page, searchKey]);
useEffect(() => {
getData();
}, []);
return (
<div>
<Select
multiple={true}
IconComponent={() => (
<svg
width="12"
height="16"
viewBox="0 0 12 16"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M6.52567 15.7821L11.287 11.0208C11.5775 10.7303 11.5775 10.2591 11.287 9.96863C10.9964 9.67807 10.5254 9.67807 10.2349 9.96863L6.74356 13.4599L6.74356 0.743959C6.74356 0.333115 6.41044 0 5.9996 0C5.58882 0 5.25564 0.333115 5.25564 0.743959L5.25564 13.4599L1.76433 9.96875C1.47377 9.67819 1.00275 9.67819 0.712193 9.96875C0.567032 10.114 0.494303 10.3044 0.494303 10.4948C0.494303 10.6852 0.567032 10.8756 0.712193 11.0209L5.47353 15.7821C5.76409 16.0727 6.23511 16.0727 6.52567 15.7821Z"
fill="#666666"
/>
</svg>
)}
value={checkedTopicList}
onChange={(e: any) => {
console.log(e);
}}>
<TopicList list={topicList} checkedList={checkedTopicList} />
</Select>
</div>
);
};
export default TopicFeedDropdownSelector;
问题是,只要列表在内部呈现,onChange 函数就不会被触发,但是如果我在父组件中编写逻辑,它就像一个魅力。
为什么会这样,我希望列表在不同的组件中单独呈现,我怎样才能实现?
答:
0赞
Viiiinie
11/12/2023
#1
我不是 react 的专家,但我认为你必须将输入从渲染函数中剔除,因为你收集数据并且这些数据一次又一次地被重置。您必须创建一个静态组件。
希望能帮到你OnChange
评论
0赞
Gaurav Rajput
11/12/2023
不,我认为不是这样。
1赞
Obydul Islam Khan
11/12/2023
#2
如果您阅读 MUI Select children props 说明,则表示当 native 为 false 时,MenuItem 元素必须是直接后代。 (附截图)
此外,最好为列表项创建组件,而不是为整个列表创建组件。 前任。
<Select
multiple={true}
IconComponent={() => (
<svg
width="12"
height="16"
viewBox="0 0 12 16"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M6.52567 15.7821L11.287 11.0208C11.5775 10.7303 11.5775 10.2591 11.287 9.96863C10.9964 9.67807 10.5254 9.67807 10.2349 9.96863L6.74356 13.4599L6.74356 0.743959C6.74356 0.333115 6.41044 0 5.9996 0C5.58882 0 5.25564 0.333115 5.25564 0.743959L5.25564 13.4599L1.76433 9.96875C1.47377 9.67819 1.00275 9.67819 0.712193 9.96875C0.567032 10.114 0.494303 10.3044 0.494303 10.4948C0.494303 10.6852 0.567032 10.8756 0.712193 11.0209L5.47353 15.7821C5.76409 16.0727 6.23511 16.0727 6.52567 15.7821Z"
fill="#666666"
/>
</svg>
)}
value={checkedTopicList}
onChange={(e) => {
console.log(e.target.value);
setCheckedTopicList(e.target.value)
}}>
{
topicList.map((topic) => <MenuItem key={topic.id} value={topic.id} role="option">
<TopicItem name={topic.name} id={topic.id} checkedList={checkedTopicList} />
</MenuItem>)
}
</Select>
TopicItem Component:
function TopicItem({id, name, checkedList}) {
return (
<div className="topicTile">
<Checkbox checked={checkedList.includes(id)} />
<span>{name}</span>
</div>
)}
Another Way:
const options = useMemo(() => {
return topicList.map((topic) => <MenuItem key={topic.id} value={topic.id} role="option">
<div className="topicTile">
<Checkbox checked={checkedTopicList.includes(topic.id)} />
<span>{topic.name}</span>
</div>
</MenuItem>)
}, [topicList, checkedTopicList])
And implement Select like below:
<Select
multiple={true}
IconComponent={() => (
<svg
width="12"
height="16"
viewBox="0 0 12 16"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M6.52567 15.7821L11.287 11.0208C11.5775 10.7303 11.5775 10.2591 11.287 9.96863C10.9964 9.67807 10.5254 9.67807 10.2349 9.96863L6.74356 13.4599L6.74356 0.743959C6.74356 0.333115 6.41044 0 5.9996 0C5.58882 0 5.25564 0.333115 5.25564 0.743959L5.25564 13.4599L1.76433 9.96875C1.47377 9.67819 1.00275 9.67819 0.712193 9.96875C0.567032 10.114 0.494303 10.3044 0.494303 10.4948C0.494303 10.6852 0.567032 10.8756 0.712193 11.0209L5.47353 15.7821C5.76409 16.0727 6.23511 16.0727 6.52567 15.7821Z"
fill="#666666"
/>
</svg>
)}
value={checkedTopicList}
onChange={(e) => {
console.log(e.target.value);
setCheckedTopicList(e.target.value)
}}>
{options}
</Select>
I hope this helps you understand how MUI Select works. Let me know if you have any questions.
评论