如何在 ReactJS 中制作可重复使用的下拉过滤器,它是 DRY 并且可以在同一组件中使用两次
How to make a reusable dropdown filter in ReactJS which is DRY and can be used twice in the same component
如您所见,我使用了两个下拉过滤器 select 选项,该选项是使用 divs 自定义的,而不是 select 选项。为了重用这个自定义的 select 选项,我正在寻找一种可重用的方式,这样我就可以重用下拉过滤器一次,而不是复制非 DRY 的 de 代码。如何创建两个这样的下拉过滤器?
最重要的是我能够将 selected 值分开。
interface TableComponentProps {
columns: Array<any>;
}
export const TableComponent: FC<TableComponentProps> = ({ columns}) => {
const [columnShow, setColumnShow] = useState<string>("");
const [openDropdown, setOpenDropdown] = useState(false);
const wrapperRef = useRef(null);
const data = useMemo(() => TableContent, []);
const useOutsideAlerter = (ref: any) => {
useEffect(() => {
const handleClickOutside = (event: any) => {
if (ref.current && !ref.current.contains(event.target)) {
setOpenDropdown(false)
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}
useOutsideAlerter(wrapperRef)
const showColumn = () => {
let newArray: any = [];
console.log(newArray)
}
const dropdownFilter = (selectedColumn: string) => {
setColumnShow(selectedColumn);
setOpenDropdown(false);
showColumn()
}
const toggleDropdownOpen = () => setOpenDropdown(!openDropdown);
return (
<div>
<TableFilter>
<TableFilterBlock ref={wrapperRef}>
<TableFilterInput onClick={() => toggleDropdownOpen()}>
{columnShow.length > 0 ? columnShow : "Select"}</TableFilterInput>
<TableFilterDropdown toggleDropdown={openDropdown}>
{columns.slice(1).map((item, index) => (
<TableDropdownList key={index}>
<div onClick={() => dropdownFilter(item.id)}>
{item.id}
</div>
</TableDropdownList>
))}
</TableFilterDropdown>
</TableFilterBlock>
</TableFilter>
<TableFilter>
<TableFilterBlock ref={wrapperRef}>
<TableFilterInput onClick={() => toggleDropdownOpen()}>
{columnShow.length > 0 ? columnShow : "Select"}</TableFilterInput>
<TableFilterDropdown toggleDropdown={openDropdown}>
{columns.slice(1).map((item, index) => (
<TableDropdownList key={index}>
<div onClick={() => dropdownFilter(item.id)}>
{item.id}
</div>
</TableDropdownList>
))}
</TableFilterDropdown>
</TableFilterBlock>
</TableFilter>
<Table columns={columns} data={data} hiddenColumns={columnShow}/>
</div>
)
}
在 React 中,如果你想重用代码片段,你需要使用组件,特别是所谓的提取组件。 React Components and Props > Extracting Components 该页面解释了我在这里为您所做的以下内容。
首先您需要为下拉菜单创建一个组件,并评估哪些代码对于下拉菜单+按钮是唯一的。
const InlineComponent = ({
columns,
showColumn,
onSelect
}) => {
// move the dropdown logic here
const ref = useRef();
const [name, setName] = useState<string>("");
const [open, setOpen] = useState(false);
const openDropdown = () => setOpen(true);
const itemClick = (selectedColumn: string) => {
setName(selectedColumn);
setOpen(false);
showColumn();
onSelect(selectedColumn);
};
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target)) {
setOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
return (
<TableFilter>
<TableFilterBlock ref={ref}>
<TableFilterInput onClick={() => openDropdown()}>
{name.length > 0 ? name : "Select"}
</TableFilterInput>
<TableFilterDropdown toggleDropdown={open}>
{columns.slice(1).map((item, index) => (
<TableDropdownList key={index}>
<div onClick={() => itemClick(item.id)}>{item.id}</div>
</TableDropdownList>
))}
</TableFilterDropdown>
</TableFilterBlock>
</TableFilter>
);
};
然后从原始位置引用它并传入任何共享道具。
export const TableComponent: FC<TableComponentProps> = ({ columns }) => {
const [hiddenCol, setHiddenCol] = useState<string>("");
const data = useMemo(() => TableContent, []);
const showColumn = () => {
let newArray: any = [];
console.log(newArray);
};
return (
<div>
{/* add the newly created components here */}
<InlineComponent
columns={columns}
showColumn={showColumn}
onSelect={setHiddenCol}
/>
<InlineComponent
columns={columns}
showColumn={showColumn}
onSelect={setHiddenCol}
/>
<Table columns={columns} data={data} hiddenColumns={hiddenCol} />
</div>
);
};
公平警告我没有测试 运行 此代码,您应该自己评估哪些部分需要保留在何处。
如您所见,我使用了两个下拉过滤器 select 选项,该选项是使用 divs 自定义的,而不是 select 选项。为了重用这个自定义的 select 选项,我正在寻找一种可重用的方式,这样我就可以重用下拉过滤器一次,而不是复制非 DRY 的 de 代码。如何创建两个这样的下拉过滤器?
最重要的是我能够将 selected 值分开。
interface TableComponentProps {
columns: Array<any>;
}
export const TableComponent: FC<TableComponentProps> = ({ columns}) => {
const [columnShow, setColumnShow] = useState<string>("");
const [openDropdown, setOpenDropdown] = useState(false);
const wrapperRef = useRef(null);
const data = useMemo(() => TableContent, []);
const useOutsideAlerter = (ref: any) => {
useEffect(() => {
const handleClickOutside = (event: any) => {
if (ref.current && !ref.current.contains(event.target)) {
setOpenDropdown(false)
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}
useOutsideAlerter(wrapperRef)
const showColumn = () => {
let newArray: any = [];
console.log(newArray)
}
const dropdownFilter = (selectedColumn: string) => {
setColumnShow(selectedColumn);
setOpenDropdown(false);
showColumn()
}
const toggleDropdownOpen = () => setOpenDropdown(!openDropdown);
return (
<div>
<TableFilter>
<TableFilterBlock ref={wrapperRef}>
<TableFilterInput onClick={() => toggleDropdownOpen()}>
{columnShow.length > 0 ? columnShow : "Select"}</TableFilterInput>
<TableFilterDropdown toggleDropdown={openDropdown}>
{columns.slice(1).map((item, index) => (
<TableDropdownList key={index}>
<div onClick={() => dropdownFilter(item.id)}>
{item.id}
</div>
</TableDropdownList>
))}
</TableFilterDropdown>
</TableFilterBlock>
</TableFilter>
<TableFilter>
<TableFilterBlock ref={wrapperRef}>
<TableFilterInput onClick={() => toggleDropdownOpen()}>
{columnShow.length > 0 ? columnShow : "Select"}</TableFilterInput>
<TableFilterDropdown toggleDropdown={openDropdown}>
{columns.slice(1).map((item, index) => (
<TableDropdownList key={index}>
<div onClick={() => dropdownFilter(item.id)}>
{item.id}
</div>
</TableDropdownList>
))}
</TableFilterDropdown>
</TableFilterBlock>
</TableFilter>
<Table columns={columns} data={data} hiddenColumns={columnShow}/>
</div>
)
}
在 React 中,如果你想重用代码片段,你需要使用组件,特别是所谓的提取组件。 React Components and Props > Extracting Components 该页面解释了我在这里为您所做的以下内容。
首先您需要为下拉菜单创建一个组件,并评估哪些代码对于下拉菜单+按钮是唯一的。
const InlineComponent = ({
columns,
showColumn,
onSelect
}) => {
// move the dropdown logic here
const ref = useRef();
const [name, setName] = useState<string>("");
const [open, setOpen] = useState(false);
const openDropdown = () => setOpen(true);
const itemClick = (selectedColumn: string) => {
setName(selectedColumn);
setOpen(false);
showColumn();
onSelect(selectedColumn);
};
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target)) {
setOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
return (
<TableFilter>
<TableFilterBlock ref={ref}>
<TableFilterInput onClick={() => openDropdown()}>
{name.length > 0 ? name : "Select"}
</TableFilterInput>
<TableFilterDropdown toggleDropdown={open}>
{columns.slice(1).map((item, index) => (
<TableDropdownList key={index}>
<div onClick={() => itemClick(item.id)}>{item.id}</div>
</TableDropdownList>
))}
</TableFilterDropdown>
</TableFilterBlock>
</TableFilter>
);
};
然后从原始位置引用它并传入任何共享道具。
export const TableComponent: FC<TableComponentProps> = ({ columns }) => {
const [hiddenCol, setHiddenCol] = useState<string>("");
const data = useMemo(() => TableContent, []);
const showColumn = () => {
let newArray: any = [];
console.log(newArray);
};
return (
<div>
{/* add the newly created components here */}
<InlineComponent
columns={columns}
showColumn={showColumn}
onSelect={setHiddenCol}
/>
<InlineComponent
columns={columns}
showColumn={showColumn}
onSelect={setHiddenCol}
/>
<Table columns={columns} data={data} hiddenColumns={hiddenCol} />
</div>
);
};
公平警告我没有测试 运行 此代码,您应该自己评估哪些部分需要保留在何处。