【问题标题】:Set state for dynamically generated component in React在 React 中为动态生成的组件设置状态
【发布时间】:2022-10-15 14:26:09
【问题描述】:

我正在重用几个外部组件来在strapi 应用程序中创建我的自定义组合框。 值是从服务器接收的,所以我需要动态添加选项。 目前有以下代码:

import React, { useState, useEffect } from "react";
import {
  Combobox,
  ComboboxOption
} from "@strapi/design-system";

export default function ComboboxCustom({
  valuesList,
  valueSelected
}) {
  const [value, setValue] = useState('');
  const combo = (<Combobox label="Country" value={value} onChange={setValue}>
    {valuesList.map((entry) => {
      return(
        <ComboboxOption value="{entry.id}">{entry.name}</ComboboxOption>
      );
    })}
  </Combobox>);
  // setValue(valueSelected)
  return combo;
}

一切都很顺利,直到我尝试根据另一组数据设置“选定”选项。在静态世界中,我可以说useState(valueSelected),它会起作用。但是由于代码是动态生成的,还没有相关的选项,所以我遇到了“无法获得未定义的'props'属性”这样的失败。

我试图将此组合框放入一个变量中,并在创建和返回它之间设置状态(在 return 语句之前注释 setValue 行),但随后应用程序进入一个循环并返回“太多重新渲染”。

有谁知道如何更改/重写它以便能够为动态创建的组合框设置选定的值?

【问题讨论】:

    标签: javascript reactjs combobox programmatically-created


    【解决方案1】:

    所以我假设这些值是动态获取的并传递给 ComboboxCustom。 我认为您可以在 useEffect 中添加 setValue(valueSelected)。 onChange 道具 valueSelected.something 之类的,

    使用效果(()=> {

       setValue(valueSelected)
    
    }, [valueSelected])
    

    还可以在尚未加载值时处理返回。就像在做 valuesList.map 之前一样,首先检查 valueList 是否? (渲染实际):(渲染为空)

    希望这可以帮助!!

    谢谢, 阿努

    【讨论】:

      【解决方案2】:

      最后,我根据@Anu 的回答得到了可行的解决方案。 因为 valuesList 是从另一个钩子获取的 GET 请求,我必须检查值是否已经存在(第一个钩子命中会给出 [])并将 Combobox 状态更新绑定到 valuesList 的更改。虽然我不认为这个解决方案是完美的。

      import React, { useState, useEffect } from "react";
      import {
        Combobox,
        ComboboxOption
      } from "@strapi/design-system";
      
      export default function ComboboxCustom({
        valuesList,
        valueSelected,
      }) {
        const [value, setValue] = useState('');
        let combo = null;
        useEffect(() => {
          if(combo && combo?.props?.children?.length > 0 && valuesList.length > 0) {
            setValue(valueSelected)
          }
       }, [valueSelected, valuesList])
      
        combo = (<Combobox label="Country" value={value?.toString()} onChange={setValue}>
          {valuesList.map((entry) => {
            return(
              <ComboboxOption value={entry?.id?.toString()}>{entry.name}</ComboboxOption>
            );
          })}
        </Combobox>);
        return combo;
      }
      

      之后,我决定避免基于已发布的自定义组件创建自定义组件,因为我需要添加和处理在现有组件中为我们添加的事件侦听器。所以我将此代码直接放入我的模态中,它也可以工作:

      const [countries, setCountries] = useState([]);
      const [deliveryCountryValue, setDeliveryCountryValue] = useState('');
      
      useEffect(async () => {
        const countriesReceived = await countryRequests.getAllCountries();
        setCountries(countriesReceived);
      }, []);
      
      useEffect(() => {
        // If there is no selected value yet, set the one we get from order from server
        const valueDelivery = deliveryCountryValue != '' ? deliveryCountryValue : order.country?.id;
        if(countries.length > 0) {
          setDeliveryCountryValue(valueDelivery);
          order.country = countries.find(x => x.id == valueDelivery);
        }
      }, [deliveryCountryValue, countries])
      
      
      <Combobox key='delivery-combo' label="Country" value={deliveryCountryValue?.toString()} onChange={setDeliveryCountryValue}>
        {countries.map((entry) => {
         return(
            <ComboboxOption key={'delivery'+entry.id} value={entry?.id?.toString()}>{entry.name}</ComboboxOption>
          );
        })}
      </Combobox>
      

      【讨论】:

        猜你喜欢
        • 2019-02-17
        • 2014-09-28
        • 2017-08-17
        • 2018-10-30
        • 2020-12-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-17
        相关资源
        最近更新 更多