简体   繁体   English

如何设置'react-select'multi的'defaultValue'?

[英]How to set the 'defaultValue' of 'react-select' multi?

I'm new in ReactJS and I'm still trying to understand the lifecycle of the components.我是 ReactJS 的新手,我仍在尝试了解组件的生命周期。 I've been trying to set the default value of a multi react-select for sometime, but somehow it simply doesn't work.一段时间以来,我一直在尝试设置多反应选择的默认值,但不知何故它根本不起作用。 Since I'm following the ' react-select ' documentation exactly the way it says, I think that my problem is relationed to React's components lifecycle.由于我完全按照“ react-select ”文档的说明进行操作,因此我认为我的问题与 React 的组件生命周期有关。

What I'm trying to do: The objective is to make a 'edit user' screen.我想要做的是:目标是制作一个“编辑用户”屏幕。 The multi select is where will be setted the technologies that the User works with.多选是设置用户使用的技术的地方。 One User can have lots of techs.一个用户可以拥有很多技术。

(I'm posting here only the code that is related to the problem, making my problem easier to understand) (我在这里只发布与问题相关的代码,使我的问题更容易理解)

Getting all 'Techs' from the database:从数据库中获取所有“技术”:

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);
    });
}, []);

Getting User's techs from the database:从数据库中获取用户的技术:

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);
    });
}, []);

After that, I'm creating a State called 'userTechsForSelect', that should be an array of objects.之后,我创建了一个名为“userTechsForSelect”的状态,它应该是一个对象数组。 Those objects must have only 2 atributes: 'value' and 'label', just like the State called 'allTechs', 'cause those are the atributes that 'react-select' is asking on it's documentation.这些对象必须只有 2 个属性:“值”和“标签”,就像称为“allTechs”的状态一样,因为这些是“react-select”在其文档中要求的属性。 ( https://react-select.com/home ) ( https://react-select.com/home )

Populating 'userTechsForSelect':填充“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]);

Now, when I intantiate the 'Select' on my component, I use the States mentioned previously ( 'allTechs' as 'options' and 'userTechsForSelect' as 'defaultValue' ) to set its atributes:现在,当我在我的组件上初始化 'Select' 时,我使用前面提到的状态( 'allTechs' 作为 'options''userTechsForSelect' 作为 'defaultValue' )来设置它的属性:

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

The options are being setted, but the default value is not.正在设置选项,但未设置默认值。 My guess is: the 'Select' component is being rendered before 'userTechsForSelect' receives its values.我的猜测是:在 'userTechsForSelect' 接收到它的值之前,'Select' 组件正在呈现。 But if a put a ' console.log(userTechsForSelect) ' before the 'Select' tag, I can see that the component is being rendered many times, and while the state is empty on first renders, it is not on the last ones.但是如果在 'Select' 标签之前放一个 ' console.log(userTechsForSelect) ',我可以看到组件被渲染了很多次,虽然第一次渲染时状态为空,但它不是最后一次。

The component exactly the way it's being rendered: [Img]Select组件完全按照它的呈现方式: [Img]Select

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

Can anyone help me and tell why are the default values not being setted?谁能帮助我并告诉我为什么没有设置默认值? If you want me to post any other code, just ask!如果您想让我发布任何其他代码,请询问! Thank you !谢谢

Edit 1:编辑1:

Even when I put the defaultValue of the Select as an array, it keeps not displaying the techs that the User has.即使我把 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>

But, when I change the defaultValue to a fixed object (like I'm showing bellow), it works (even if I don't put it as an array, like defaultValue={exampleValue[0]} )但是,当我将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>
)

The result is: here结果是:这里

Edit 2:编辑2:

As asked, I'm going to console.log the options State and the defaultValue State before the Select, so you can see that the defaultValue should be matching with one of the options.正如所问的那样,我将在options之前将options状态和defaultValue状态记录到console.log ,因此您可以看到defaultValue应该与选项之一匹配。

The code:编码:

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

(The console.log 's are going to appear many times, 'cause the component renders many times as well, so I put another console.log before each one to make it easier to see) console.log会出现很多次,因为组件也会渲染很多次,所以我在每个之前都放了一个console.log以便更容易看到)

The result: [Img]console.log results结果: [Img]console.log 结果

As you can see, the userTechsForSelect array is empty in the beginning, but then it is not.如您所见, userTechsForSelect数组一开始是空的,但后来不是。 I think that the Select component is being rendered before userTechsForSelect gets its values我认为在userTechsForSelect获取其值之前呈现Select组件

由于您已将isMulti设为 true,因此您的defaultValue应该是一个数组

defaultValue={[userTechsForSelect[0]]}

I just solved it!我刚刚解决了!

As I was suspecting, the component was being rendered before userTechsForSelect had any value.正如我所怀疑的那样,组件在userTechsForSelect具有任何价值之前就被渲染了。 So I created a function that verifies if userTechsForSelect.length > 0 and returns the component only if this condition is satisfied所以我创建了一个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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM