Как установить 'defaultValue' из'act-select 'multi? - PullRequest
0 голосов
/ 14 марта 2020

Я новичок в ReactJS и все еще пытаюсь понять жизненный цикл компонентов. Я пытался установить значение по умолчанию для мультиреактивного выбора в течение некоторого времени, но каким-то образом это просто не работает. Поскольку я в точности следую документации ' реагировать на выбор ', я думаю, что моя проблема связана с жизненным циклом компонентов React.

Что я пытаюсь to do: Цель состоит в том, чтобы создать экран редактирования пользователя. Мультивыбор - это то место, где будут установлены технологии, с которыми работает Пользователь. У одного пользователя может быть много техников.

(я публикую здесь только код, связанный с проблемой, чтобы облегчить понимание моей проблемы)

Получение всех 'техников 'из базы данных:

const [allTechs, setAllTechs] = useState([]);

useEffect(() => {
    async function getAllTechs(){
        const response = await api.get('/api/techs');

        return response.data.docs;
    }

    getAllTechs().then(result => {
        const list = [];

        result.forEach(r => {
            let tech = {value: r._id, label: r.name};

            list.push(tech);
        })

        setAllTechs(list);
    });
}, []);

Получение технических данных пользователя из базы данных:

const [techs, setTechs] = useState([]);

let { id } = useParams();

useEffect(() => {
    async function getData() {
        const response = await api.get(`api/users/${id}`);

        return response.data;
    }

    getData().then(result => {
        setTechs(result.techs);
    });
}, []);

После этого я создаю состояние под названием' userTechsForSelect ', который должен быть массивом объектов. Эти объекты должны иметь только 2 атрибута: «значение» и «метка», так же как и состояние «allTechs», потому что это атрибуты, которые «реагирует на выбор» запрашивает в своей документации. (https://react-select.com/home)

Заполнение 'userTechsForSelect':

const [userTechsForSelect, setUserTechsForSelect] = useState([]);

useEffect(() => {
    async function getInitialTechValues(){
        const list = [];

        techs.map(t => {
            let tech = {value: t._id, label: t.name};
            list.push(tech);
        })

        setUserTechsForSelect(list);
    }

    getInitialTechValues();

}, [techs]);

Теперь, когда я создаю 'Select' на моем компоненте, Я использую упомянутые ранее состояния ( 'allTechs' как 'опции' и 'userTechsForSelect' как 'defaultValue' ), чтобы установить его атрибуты:

return(
    <Select
        className="editUserReactSelect"
        options={allTechs}
        defaultValue={userTechsForSelect[0]}
        closeMenuOnSelect={false}
        placeholder="Select"
        isMulti
        styles={colourStyles}
    />
)

Параметры устанавливаются, но значение по умолчанию - нет. Я предполагаю, что компонент «Выбрать» визуализируется до того, как «userTechsForSelect» получит свои значения. Но если перед тегом 'Select' поставить ' console.log (userTechsForSelect) ', я могу видеть, что компонент рендерится много раз, и хотя состояние пусто при первом рендеринге, это не на последних.

Компонент точно так, как он отображается: [Img] Выбрать

Console.log результат : [Img] Console.log

Кто-нибудь может мне помочь и сказать, почему не устанавливаются значения по умолчанию? Если вы хотите, чтобы я опубликовал любой другой код, просто спросите! Спасибо !

Редактировать 1:

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

<label className="editUserLabel">Tecnologias
    {console.log(userTechsForSelect[0])}
    <Select
          className="editUserReactSelect"
          options={allTechs}
          defaultValue={[userTechsForSelect[0]]}
          closeMenuOnSelect={false}
          placeholder="Selecione"
          isMulti
          styles={colourStyles}
     />
</label>

Но когда я заменяю defaultValue на фиксированный объект (как я показываю ниже), он работает (даже если я не надену не помещайте это как массив, как defaultValue={exampleValue[0]})

const exampleValue = [{value: '5e6067ddef8a973de092403d', label: 'NodeJS'}];

return(
    <label className="editUserLabel">Tecnologias
        {console.log(userTechsForSelect[0])}
         <Select
             className="editUserReactSelect"
             options={allTechs}
             defaultValue={exampleValue[0]}
             closeMenuOnSelect={false}
             placeholder="Selecione"
             isMulti
             styles={colourStyles}
         />
     </label>
)

Результат: здесь

Edit 2:

Как я и просил, я собираюсь console.log options State и defaultValue State перед выбором, так что вы можете видеть, что defaultValue должен соответствовать одному из вариантов.

Код:

<label className="editUserLabel">Tecnologias
    {console.log("allTechs: ")}
    {console.log(allTechs)}

    {console.log("userTechsForSelect: ")}
    {console.log(userTechsForSelect)}
    <Select
        className="editUserReactSelect"
        options={allTechs}
        defaultValue={[userTechsForSelect[0]]}
        closeMenuOnSelect={false}
        placeholder="Selecione"
        isMulti
        styles={colourStyles}
    />
</label>

(console.log появятся много раз, потому что компонент также рендерится много раз, поэтому я ставлю еще console.log перед каждым, чтобы его было легче видеть)

Результат: [Img] console.log results

Как видите, массив userTechsForSelect в начале пуст, но тогда это не так. Я думаю, что компонент Select рендерится до того, как userTechsForSelect получит свои значения

Ответы [ 2 ]

0 голосов
/ 14 марта 2020

Я только что решил!

Как я и подозревал, компонент рендерился до того, как userTechsForSelect имел какое-либо значение. Поэтому я создал function, который проверяет, если userTechsForSelect.length > 0 и возвращает компонент, только если это условие удовлетворяется

function EditUser() {
    // All useStates and useEffects that I posted before

    // What I modified:
    function createReactSelect(){
        if (userTechsForSelect.length > 0){
            return (
                <label className="editUserLabel">Tecnologias         
                    <Select
                        className="editUserReactSelect"
                        options={allTechs}
                        defaultValue={[userTechsForSelect[0]]}
                        closeMenuOnSelect={false}
                        placeholder="Selecione"
                        isMulti
                        styles={colourStyles}
                    />
                </label>
            );
        }
    }

    return {createReactSelect()};
}

export default EditUser;
0 голосов
/ 14 марта 2020

Поскольку вы передали isMulti как true, ваш defaultValue должен быть массивом

defaultValue={[userTechsForSelect[0]]}
...