reactjs 组件正在将不受控制的自动完成更改为受控制

ca1c2owp  于 2023-02-15  发布在  React
关注(0)|答案(6)|浏览(174)

你能告诉我为什么我会得到错误"一个组件正在将一个不受控的自动完成更改为受控的。元素不应该从不受控切换到受控(反之亦然)。在组件的生命周期内决定使用受控或不受控的自动完成元素。"
组分:

function AutoComplete(props) {

  const defaultProps = {
    options: props.options,
    getOptionLabel: option => option.name,
  };

  const handleChange = (e, value) => {
    props.onChange(value);
  };

  return (
    <Autocomplete
      {...defaultProps}
      renderInput={params => (
        <TextField {...params} label={props.label} margin="normal" />
      )}
      onChange={handleChange}
      value={props.value}
    />
  );
}

调用自动完成:

<Controller
                control={control}
                name = 'country'
                as = {
                  <AutoComplete
                    options={countryOptions}
                    onChange={selectCountryHandler}
                    label="Country"
                    value={selectedCountry  || ''}
                  />
                } />

我怎样才能解决这个错误?

dgenwo3n

dgenwo3n1#

您确保了value属性从未被定义过,但您必须对inputValue执行相同的操作。
1.带有value/onChange属性组合的“value”状态。此状态表示用户选择的值,例如按Enter键时。

  1. inputValue/onInputChange属性组合的“输入值”状态。此状态表示文本框中显示的值。
    这️两个状态是孤立的,它们应该被独立地控制。
    未定义inputValue属性时,组件将变为不受控制,反之亦然。
    如果在以下示例中从React.useState('')中删除空字符串,则将获得相同的错误消息,因为首次渲染期间的inputValueundefined
import React from 'react'
import TextField from '@material-ui/core/TextField'
import Autocomplete from '@material-ui/lab/Autocomplete'

const options = ['Option 1', 'Option 2']

export default function AutocompleteLab() {
  const [value, setValue] = React.useState(options[0])
  const [inputValue, setInputValue] = React.useState('')

  return (
    <div>
      <div>{`value: ${value !== null ? `'${value}'` : 'null'}`}</div>
      <div>{`inputValue: '${inputValue}'`}</div>
      <br />
      <Autocomplete
        value={value}
        onChange={(_, newValue) => {
          setValue(newValue)
        }}
        inputValue={inputValue}
        onInputChange={(_, newInputValue) => {
          setInputValue(newInputValue)
        }}
        options={options}
        style={{ width: 300 }}
        renderInput={(params) => <TextField {...params} label="Name" variant="outlined" />}
      />
    </div>
  )
}
o8x7eapl

o8x7eapl2#

如果未选择任何值,则需要添加|| null以防止自动完成进入不受控模式:

<Autocomplete {...props} value={props.value || null} />

如果您将value={undefined}传递给自动完成组件,它将以“uncontrolled”模式启动,这意味着它保持自己的内部状态。然后,如果您稍后提供value,它将引发“A component is changing”错误。但是,如果您传递value={null}而不是value={undefined},则会导致自动完成以受控模式启动。自动完成将假定您将提供状态,而不是保持它自己,错误就会消失。

z4iuyo4d

z4iuyo4d3#

我通过删除default value解决了这个问题。

<Autocomplete
                multiple
                id="multiple-limit-tags"
                options={(option) => option.label}
                getOptionLabel={(option) => option}
                // defaultValue={options || []}
                renderInput={(params) => <TextField {...params} label="My Label" />}           
              />

如何解决这个问题并不明显,文档也没有多大帮助。我发现文档中的一个复制粘贴示例会导致这个错误,这很奇怪。我猜这个示例之所以有效,是因为选择是硬编码的。

d5vmydt9

d5vmydt94#

前面的答案是绝对正确的,但是我花了20分钟才算出inputValue应该是value,下面是我的工作示例:

export default function AddModal(): ReactElement {
const [resource, setResource] = useState('one');
<Autocomplete
    id="autocomplete"
    options={['one', 'two']}
    defaultValue={resource}
    value={resource}
    PopperComponent={StyledPopper}
    onChange={(event, newInputValue) => setResource(newInputValue)}
    renderInput={(params) => <TextField {...params} />}
/>
soat7uwm

soat7uwm5#

我今天遇到了同样的问题,但我能够通过提供一个默认值null以及在它不存在的情况下提供一个null值来解决它。我将留下对我有效的代码:

<Autocomplete
    value={filters.tag || null}
    defaultValue={null}
    options={tags || []}
    getOptionLabel={(option) => option}
    renderInput={(params) => (
        <TextField {...params} label="Search" variant='outlined' size='small' />
    )}
    fullWidth
    onChange={(event, value) => {
           if (value) {
               setFilters({ ...filters, tag: value });
           } else {
               setFilters({ ...filters, tag: '' });
           }
    }}
/>
vm0i2vca

vm0i2vca6#

对于我来说,我通过更新onChange函数并添加|| null而不是删除默认值修复了这个问题,因为我仍然需要它,下面是代码

<Box mt={2}>
  <Controller
    control={control}
    name="thematic"
    rules={{
      required: 'Veuillez choisir une réponse',
    }}
    render={({ field: { onChange } }) => (
      <Autocomplete
        defaultValue={
          questionData?.thematic ? questionData?.thematic : null
        }
        options={thematics}
        getOptionLabel={(option) => option.name}
        onChange={(event, values) => {
          onChange(values || null)
        }}
        renderInput={(params) => (
          <TextField
            {...params}
            label="Thématique"
            placeholder="Thématique"
            helperText={errors.thematic?.message}
            error={!!errors.thematic}
          />
        )}
      />
    )}
  />
</Box>

对于带有选项的自动完成,这是一个简单的数组,没有对象,你可以简单地这样做,你想得到任何问题

<Box mt={2}>
  <Controller
    control={control}
    name="type"
    rules={{
      required: 'Veuillez choisir une réponse',
    }}
    render={({ field: { onChange, value } }) => (
      <Autocomplete
        freeSolo
        options={['Champ', 'Sélection', 'Choix multiple']}
        onChange={(event, values) => onChange(values)}
        value={value}
        renderInput={(params) => (
          <TextField
            {...params}
            label="Type de la question"
            variant="outlined"
            onChange={onChange}
            helperText={errors.type?.message}
            error={!!errors.type}
          />
        )}
      />
    )}
  />
</Box>

如果使用react-hook-form,则可以在useForm中设置默认值

const {
  handleSubmit,
  control,
  watch,
  register,
  formState: { errors },
} = useForm({
  defaultValues: {
    ...
    type: questionData?.type ? mapperQuestionType[questionData?.type] : '',
  },
})

相关问题