React Admin:如何通过SelectInput调用useStore设置全局变量?
解决React Admin中SelectInput同步useStore值的问题
你遇到的编译错误是因为React Admin的Filter组件会自动为内部输入组件绑定onChange事件来管理过滤表单状态,直接覆盖该事件会破坏默认的状态初始化逻辑。下面提供两种可行的解决方案:
方案一:监听List过滤状态同步到useStore
通过useListContext获取当前List组件的过滤参数,监听其变化并同步到useStore中,无需修改SelectInput的默认事件:
import React, { useEffect } from "react"; import { List, Datagrid, TextField, DateField, Filter, TextInput, SelectInput, useStore, useGetList, useListContext } from "react-admin"; const SeatsFilter = (props) => { return ( <Filter {...props}> <TextInput label="Name" source="name" alwaysOn /> <SelectInput label="Select Election" source="electionCode" choices={props.allElections || []} alwaysOn /> </Filter> ); }; const SeatsList = (props) => { const [electionCode, setElectionCode] = useStore("electionCode", ""); const [allElections, setAllElections] = useStore("allElections", []); const { data } = useGetList("elections"); const { filters } = useListContext(); // 监听过滤参数中的electionCode变化,同步到useStore useEffect(() => { if (filters.electionCode !== undefined) { setElectionCode(filters.electionCode); } }, [filters.electionCode, setElectionCode]); useEffect(() => { setAllElections(data); }, [data]); return ( <List filters={<SeatsFilter allElections={allElections || []} />} {...props} sort={{ field: "name", order: "asc" }} > <Datagrid rowClick="show"> <TextField source="name" /> <DateField source="updatedAt" label="Last Updated" /> </Datagrid> </List> ); }; export default SeatsList;
方案二:自定义onChange同时更新表单和useStore
通过useFormContext获取Filter的表单上下文,在自定义的onChange中先执行React Admin的默认表单更新逻辑,再同步useStore的值:
import React, { useEffect } from "react"; import { List, Datagrid, TextField, DateField, Filter, TextInput, SelectInput, useStore, useGetList, useFormContext } from "react-admin"; const SeatsFilter = ({ allElections, setElectionCode }) => { const { form } = useFormContext(); const handleElectionChange = (value) => { // 先更新React Admin的过滤表单状态 form.change("electionCode", value); // 再同步到useStore setElectionCode(value); }; return ( <Filter> <TextInput label="Name" source="name" alwaysOn /> <SelectInput label="Select Election" source="electionCode" choices={allElections || []} alwaysOn onChange={handleElectionChange} /> </Filter> ); }; const SeatsList = (props) => { const [electionCode, setElectionCode] = useStore("electionCode", ""); const [allElections, setAllElections] = useStore("allElections", []); const { data } = useGetList("elections"); useEffect(() => { setAllElections(data); }, [data]); return ( <List filters={<SeatsFilter allElections={allElections || []} setElectionCode={setElectionCode} />} {...props} sort={{ field: "name", order: "asc" }} > <Datagrid rowClick="show"> <TextField source="name" /> <DateField source="updatedAt" label="Last Updated" /> </Datagrid> </List> ); }; export default SeatsList;
关键说明
- 方案一无需修改Filter内部逻辑,通过监听List的过滤状态实现同步,更符合React Admin的设计逻辑;
- 方案二适合需要在选择时立即执行额外逻辑的场景,但必须确保先调用
form.change维持默认过滤功能; - 原代码中
TextField source="props.electionCode"是错误用法,source属性应对应数据字段名,若要展示当前选中的electionCode,可在SeatsList中通过electionCode变量直接渲染。
内容的提问来源于stack exchange,提问作者Joshua Foxworth
相关产品推荐
相关产品推荐

