Reactjs 使用Redux存储数据填充材质UI下拉列表

Reactjs 使用Redux存储数据填充材质UI下拉列表,reactjs,redux,react-redux,material-ui,Reactjs,Redux,React Redux,Material Ui,我试图让我的Redux存储字段自动填充我导入的方法。为了完成这件事,我是否采取了正确的方法?是否需要为每个字段创建映射选项 我在每个下拉列表中插入了一个PopulateDropdown列表和每个下拉列表中的字段,但我需要根据id和文本对它们进行拆分 我是否正确访问下面的redux商店?我使用constfields=useSelector(state=>state.fields)在我的函数组件上声明了数组 更新 我将方法插入到下拉列表中,但是我认为我没有正确访问数据,这导致了问题。字段数组已被分解

我试图让我的Redux存储字段自动填充我导入的方法。为了完成这件事,我是否采取了正确的方法?是否需要为每个字段创建映射选项

我在每个下拉列表中插入了一个PopulateDropdown列表和每个下拉列表中的字段,但我需要根据id和文本对它们进行拆分

我是否正确访问下面的redux商店?我使用constfields=useSelector(state=>state.fields)在我的函数组件上声明了数组

更新 我将方法插入到下拉列表中,但是我认为我没有正确访问数据,这导致了问题。字段数组已被分解为每个下拉列表的六个不同字段,并为每个字段创建了不同的映射选项

我需要做什么才能将数据输入到方法中?我看到的示例在组件上声明了静态数组,而不是使用Redux存储

const fields = useSelector(state => state.fields);
// can destructure individual fields
const { diveSchoolList, currentList, regionList, diveTypeList, visibilityList, diveSpotList } = fields;

已导入的PopulatedDropDown方法

export const PopulateDropdown = ({ dataList = [], mappingOptions, name, label }) => {

const { title, value } = mappingOptions;

return (
<FormControl style={{ width: 200 }} >
  <InputLabel id={label}>{label}</InputLabel>
  <Select labelId={label} name={name} > 
  {dataList.map((item) => (
  <MenuItem value={item[value]}>{item[title]}</MenuItem>
  ))}
  </Select>
</FormControl>
);
};
export const PopulateDropdown=({dataList=[],mappingOptions,name,label})=>{
const{title,value}=mappingOptions;
返回(
{label}
{dataList.map((项)=>(
{项目[标题]}
))}
);
};
导入的下拉菜单

       <PopulateDropdown
           dataList={diveType}
           mappingOptions={mappingOptions}
           name="fieldName"
           label="Select dive type"
           value={dive.typeID}
           onChange={handleChange}/>

更新

我已经更新了action、reducer和populateFields方法,但是我仍然无法将redux数据映射到我的两个属性字段。在Redux树中,字段应位于fields.data.FieldList下,因为在我控制台记录它们时,这些字段会打印出来


我应该以什么方式将它们填充到标题属性等中?它现在看起来像是在填充,但是一个大的框掉了下来,我在里面看不到任何值

// select user object from redux
        const user = useSelector(state => state.user);

        // get the object with all the fields
        const fields = useSelector(state => state.fields);

        // can destructure individual fields
        const { diveSchoolList = [],
                currentList = [],
                regionList = [],
                diveTypeList = [],
                visibilityList = [],
                diveSpotList = [],
                marineTypeList = [],
                articleTypeList = []
        } = fields;

 .........


<PopulateDropdown
   dataList={fields.data.diveTypeList} // the options array
   titleProperty={fields.data.diveTypeList.diveTypeID} // option label property
   valueProperty={fields.data.diveTypeList.diveType} // option value property
   label="Dive Type Name" // label above the select
   placeholder="Select dive type" // text show when empty
   value={dive.typeID} // get value from state
   onChange={handleChange(setDive.typeID)} // update state on change
/>
//从redux中选择用户对象
const user=useSelector(state=>state.user);
//获取包含所有字段的对象
const fields=useSelector(state=>state.fields);
//可以分解单个字段
常量{DELPHOOLLIST=[],
currentList=[],
regionList=[],
diveTypeList=[],
可视性列表=[],
列表=[],
marineTypeList=[],
articleTypeList=[]
}=字段;
.........

您的
PopulateDropdown
组件看起来是正确的,只是我们需要它使用我们作为道具传递的
值和
onChange

我个人的偏好是使用单独的属性
valueProperty
titleProperty
,而不是传递单个
mappingOptions
。这样,您就不需要为每个下拉列表创建对象,只需在JSX中设置这两个属性。如果对数据进行规范化,使每个列表的元素具有相同的属性
id
label
,则可以完全删除此部分

<PopulateDropdown
  dataList={diveTypeList} // the options array
  titleProperty={"diveTypeId"} // option label property
  valueProperty={"diveType"} // option value property
  label="Dive Type Name" // label above the select
  placeholder="Select dive type" // text show when empty
  value={dive.typeID} // get value from state
  onChange={handleChange("typeId")} // update state on change
/>
因此,在组件中,我们现在只需要调用一个操作,而不是在字段中循环

useEffect(() => {
    dispatch(requireFieldData());
}, []);

您需要使用redux toolkit中的
useSelector
,或react redux中的
connect
函数将redux数据注入组件。你做得对吗?我建议你使用redux钩子来完成这项工作。如前所述,使用useSelector获取数据,使用useDispatch调度操作。你确定你做得对吗?这个答案会有帮助的:嘿,Jimbo,几周前建立了redux商店。现在看起来怎么样?如果您可以共享Github repo或CodeSandbox,它将帮助我更好地理解数据结构。我绝对认为我们可以创建一个通用组件,它将适用于所有6个列表,只需一些配置道具。看起来您所拥有的大部分都是正确的!我认为您实际上不需要将
name
属性传递给select。另外,我不需要创建
mappingOptions
对象,而是让
PopulateDropdown
组件获取两个单独的属性
valueProperty
titleProperty
。我可以给你写一个答案,但没有上一个那么深入,因为你已经掌握了窍门!我看到你在一个API调用中获取所有字段数据,这很好。如果下拉列表看起来是填充的,但是我实际上无法读取值,因为它只是一个大的白色框,这个错误听起来与什么有关?听起来好像每个选项都有一个
MenuItem
,但是我们没有提取正确的标签(这将是
MenuItem
上的
子项
属性)。这部分:
{item[titleProperty]}
在这种情况下,我应该以什么方式填充它们?看起来它可能会用valueProp={fields.data.diveTypeList.diveType)之类的东西填充它们,但是当页面重新呈现为“fields.data未定义”并且我的存储没有填充时,我会出错。我想我可以只输入dataList名称,因为它在顶部是结构化的,然后是特定的行名称。
export const requireFieldData = createAsyncThunk(
  "fields/requireData", // action name
  // don't need any argument because we are now fetching all fields
  async () => {
    const response = await diveLogFields();
    return response.data;
  },
  // only fetch when needed: https://redux-toolkit.js.org/api/createAsyncThunk#canceling-before-execution
  {
    // _ denotes variables that aren't used -  the first argument is the args of the action creator
    condition: (_, { getState }) => {
      const { fields } = getState(); // returns redux state
      // check if there is already data by looking at the didLoadData property
      if (fields.didLoadData) {
        // return false to cancel execution
        return false;
      }
    }
  }
);
const fieldsSlice = createSlice({
  name: "fields",
  initialState: {
    currentList: [],
    regionList: [],
    diveTypeList: [],
    visibilityList: [],
    diveSpotList: [],
    diveSchoolList: [],
    marineTypeList: [],
    articleTypeList: [],
    didLoadData: false,
  },
  reducers: {},
  extraReducers: {
    // picks up the pending action from the thunk
    [requireFieldData.pending.type]: (state) => {
      // set didLoadData to prevent unnecessary re-fetching
      state.didLoadData = true;
    },
    // picks up the success action from the thunk
    [requireFieldData.fulfilled.type]: (state, action) => {
      // want to replace all lists, there are multiple ways to do this
      // I am returning a new state which overrides any properties
      return {
        ...state,
        ...action.payload
      }
    }
  }
});
useEffect(() => {
    dispatch(requireFieldData());
}, []);