Сохранение выбора материала и пользовательского интерфейса с данными Redux - PullRequest
0 голосов
/ 12 октября 2019

Я пытаюсь реализовать компонент выбора Material-UI с данными из Redux, чтобы выбор сохранялся при обновлениях.

У меня есть два массива данных внутри Redux: sourceTags массив, который является моим списком интерактивных опций меню, и мой selectedTags массив, который включает выбранные опции (те, которые пользователь щелкнул). API для компонента Material-UI: здесь .

Компонент выглядит следующим образом:

import React, { useEffect, useState } from 'react';
import { Select, Input, MenuItem } from "@material-ui/core";
import { useDispatch, useSelector } from "react-redux";
import { setTags } from "../actions/search";

const MultiChipSelect = ({ source }) => {

    const dispatch = useDispatch();
    const selectedTags = useSelector(state => state.search.tags);
    const sourceTags = useSelector(state => state.settings[source].tags);

    const handleTagClick = async (e) => {
        dispatch(setTags(e.target.value)); // Sets my searchTags list in Redux.
        // The e.target.value is an array of objects, or an empty array.

    };

    return (
        <Select
        multiple
        value={selectedTags}
        onChange={handleTagClick}
        input={<Input id="select-multiple" />}
        >
        {sourceTags.map(val => (
            <MenuItem key={val._id} value={val}>
            {val.data}
            </MenuItem>
        ))}
        </Select>
    );
}

export default MultiChipSelect;

Компонент работает, по крайней мере, частично. Вот как это выглядит, когда я делаю выбор:

enter image description here

Резервное хранилище также корректно обновляется. Рад поделиться генератором действий и редуктором, но это не проблема.

Проблема в том, что при обновлении страницы массив selectedTags не отображается в компоненте. Объекты появляются внутри выделенного компонента, но не отображаются:

enter image description here

Как я могу реструктурировать этот компонент Material-UI, чтобыПравильно извлекайте данные из моего хранилища Redux и сохраняйте отображаемое выделение при обновлении, а не полагайтесь на ловушку useState, которая не соответствует, как в примерах?

Для контекста, вот чтобудет выглядеть как использование useState крючка. Имейте в виду, что этот выбор не сохраняется при обновлении:

import React, { useState } from 'react';
import { Select, Input, MenuItem } from "@material-ui/core";
import { useSelector } from "react-redux";

const MultiChipSelect = ({ source }) => {

    const sourceTags = useSelector(state => state.settings[source].tags);
    const [tags, setTags] = useState([]);

    const handleTagClick = async (e) => {
        setTags(e.target.value); // Sets my tags list.
    };

    return (
        <Select
        multiple
        value={tags}
        onChange={handleTagClick}
        input={<Input id="select-multiple" />}
        >
        {sourceTags.map(val => (
            <MenuItem key={val._id} value={val}>
            {val.data}
            </MenuItem>
        ))}
        </Select>
    );
}

export default MultiChipSelect;

1 Ответ

0 голосов
/ 12 октября 2019

Понял.

Оказывается, компонент действительно получал информацию правильно, но не отображал ее, потому что использовал функцию рендеринга по умолчанию.

Мне нужно былозамените функцию рендеринга на функцию, которая будет использовать данные из объекта. Фиксированный компонент выглядит так:

import React, { useEffect, useState } from 'react';
import { Select, Input, MenuItem } from "@material-ui/core";
import { useDispatch, useSelector } from "react-redux";
import { setTags } from "../actions/search";

const MultiChipSelect = ({ source }) => {

    const dispatch = useDispatch();
    const selectedTags = useSelector(state => state.search.tags);
    const sourceTags = useSelector(state => state.settings[source].tags);

    const handleTagClick = async (e) => {
        dispatch(setTags(e.target.value));
    };

    return (
        <Select
        multiple
        value={selectedTags}
        onChange={handleTagClick}
        input={<Input id="select-multiple" />}
        // renderValue={selected => ( // This function is necessary when using objects, because the 'label' value should display the value.data value, not just the object. This is necessary because I'm using objects instead of strings.
        //    <div>
        //      {selected.map(value => (
        //        <Chip key={value._id} label={value.data}/>
        //      ))}
        //    </div>
        //  )}
        >
        >
        {sourceTags.map(val => (
            <MenuItem key={val._id} value={val}>
            {val.data}
            </MenuItem>
        ))}
        </Select>
    );
}

export default MultiChipSelect;
...