如何设置“反应选择”多重反应的“默认值”?

时间:2020-03-13 21:08:31

标签: reactjs react-hooks react-select

我是ReactJS的新手,但我仍在尝试了解组件的生命周期。我一直在尝试将multi react-select的默认值设置为一段时间,但是以某种方式根本无法正常工作。由于我完全按照“ react-select ”文档中的说明进行操作,因此我认为我的问题与React的组件生命周期有关。

我要做什么: 目的是制作一个“编辑用户”屏幕。多选是设置用户使用技术的地方。一个用户可以拥有很多技术。

(我仅在此处发布与问题相关的代码,使我的问题更易于理解)

从数据库中获取所有“技术”:

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”的州一样,“因为这些是'react-select'在其文档中要求的属性。 (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]);

现在,当我在组件上初始化“选择”时,我将使用前面提到的状态(“ allTechs”作为“选项” 'userTechsForSelect '作为'defaultValue')来设置其属性:

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

正在设置选项,但默认值不是。我的猜测是:“选择”组件在“ userTechsForSelect”接收其值之前被渲染。但是,如果在“选择”标记之前放置“ console.log(userTechsForSelect)”,我可以看到该组件被渲染了很多次,并且在第一次渲染时该状态为空。不是最后一个。

组件的呈现方式完全相同: [Img]Select

Console.log结果: [Img]Console.log

任何人都可以帮助我,并告诉我为什么未设置默认值吗?如果您要我发布其他任何代码,请问! 谢谢

编辑1:

即使我将Select的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]}那样将其放置为数组)< / p>

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>
)

结果是: here

编辑2:

根据要求,我将在选择之前进入console.log状态和options状态,因此您可以看到defaultValue应该与选项之一。

代码:

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 :(得分:0)

由于您已传递isMulti为真,因此您的defaultValue应该是一个数组

defaultValue={[userTechsForSelect[0]]}

答案 1 :(得分:0)

我刚刚解决了!

正如我所怀疑的那样,该组件是在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;