(React, MaterialUI, Context) Автозаполнение MUI / TextField не отображает его значение при монтировании - PullRequest
0 голосов
/ 06 апреля 2020

Я использую компонент автозаполнения пользовательского интерфейса в сочетании с компонентом TextField. Все работает, как и ожидалось, за исключением одной проблемы. TextField не отображает свое входное значение при монтировании. Я проверил, что он получает значение, просто почему-то не показывается.

Функциональность, к которой я обращаюсь, заключается в том, чтобы входные данные формы сохраняли свои значения, даже когда они не подключены / смонтированы - до тех пор, пока компонент приложения root остается подключенным. Состояние формы находится на верхнем уровне приложения в Context. Форма содержит упомянутое мной поле поиска, компонент выбора MUI и кнопку отправки. Я делаю то же самое с компонентом Select, и он работает нормально, но не с Autocomplete / TextField. Связана ли эта проблема с автозаполнением?

Context. js:

import React, { createContext, useState } from 'react';

const initialState = {
  autocompleteOptions: [],
  cohortInput: 13,
  searchInput: '',
};

const Context = createContext([{}, () => {}]);

export const ContextProvider = ({ children }) => {
  const [state, setState] = useState(initialState);
  return (
    <Context.Provider value={[state, setState]}>
      {children}
    </Context.Provider>
  );
}

export default Context;

SearchField. js:

import React, { useContext } from 'react';
import Autocomplete from '@material-ui/lab/Autocomplete';
import CloseIcon from '@material-ui/icons/Close';

import Context from '../../../Context';
import TextFieldWithAdornment from './TextFieldWithAdornment';

const SearchField = () => {
  const [context, setContext] = useContext(Context); // eslint-disable-line
  const { autocompleteOptions } = context;

  return (
    <Autocomplete
      closeIcon={<CloseIcon />}
      forcePopupIcon={false}
      freeSolo={!!autocompleteOptions}
      getOptionLabel={option => option}
      options={autocompleteOptions}
      renderInput={params => <TextFieldWithAdornment {...params} />}
    />
  );
};

export default SearchField;

TextFieldWithAdornment. js:

import React, { useContext } from 'react';
import SearchIcon from '@material-ui/icons/SearchTwoTone';

import Context from '../../../Context';
import { findMatches } from './helpers';
import { StyledInputAdornment, StyledTextField } from './styles';

const TextFieldWithAdornment = ({ InputProps, ...restProps }) => {
  const [context, setContext] = useContext(Context);
  const { searchInput } = context;

  const handleChange = ({ target: { value } }) => {
    const searchInput = value;
    const autocompleteOptions = value.length ? findMatches(value) : [];
    setContext({ ...context, autocompleteOptions, searchInput });
  };

  const handleBlur = () => {
    setContext({ ...context, autocompleteOptions: [] });
  };

  const startAdornment = (
    <StyledInputAdornment position="start">
      <SearchIcon />
    </StyledInputAdornment>
  );

  return (
    <StyledTextField
      InputProps={{ ...InputProps, startAdornment }}
      onBlur={handleBlur}
      onChange={handleChange}
      value={searchInput}
      {...restProps}
    />
  );
};

export default TextFieldWithAdornment;

CohortSelect. js:
(это работает)

import React, { useContext } from 'react';

import Context from '../../../Context';
import {
  CohortSelectWrapper,
  StyledLabel,
  StyledMenuItem,
  StyledSelect,
} from './styles';

const CohortSelect = () => {
  const [context, setContext] = useContext(Context);
  const { cohortInput } = context;

  const handleChange = ({ target: { value } }) => {
    setContext({ ...context, cohortInput: value });
  };

  return (
    <CohortSelectWrapper>
      <StyledLabel>cohort</StyledLabel>
      <StyledSelect onChange={handleChange} value={cohortInput}>
        <StyledMenuItem value={11}>11</StyledMenuItem>
        <StyledMenuItem value={12}>12</StyledMenuItem>
        <StyledMenuItem value={13}>13</StyledMenuItem>
        <StyledMenuItem value={14}>14</StyledMenuItem>
      </StyledSelect>
    </CohortSelectWrapper>
  );
};

export default CohortSelect;

1 Ответ

0 голосов
/ 07 апреля 2020

Я только что понял это. У меня был TextField в качестве контролируемого компонента формы, передаваемого реквизиту onChange & value. Вместо этого мне нужно было управлять автозаполнением, используя реквизиты onInputChange и inputValue.

SearchField. js:

import React, { useContext } from 'react';
import Autocomplete from '@material-ui/lab/Autocomplete';
import CloseIcon from '@material-ui/icons/Close';

import Context from '../../../Context';
import TextFieldWithAdornment from './TextFieldWithAdornment';
import { findMatches } from './helpers';

const SearchField = () => {
  const [context, setContext] = useContext(Context);
  const { autocompleteOptions, searchInput } = context;

  const handleChange = event => {
    if (event) {
      const searchInput = event.target.value;
      const autocompleteOptions =
        event.target.value.length ? findMatches(event.target.value) : [];
      setContext({ ...context, autocompleteOptions, searchInput });
    }
  };

  const handleClear = () => {
    setContext({ ...context, autocompleteOptions: [] });
  };

  return (
    <Autocomplete
      closeIcon={<CloseIcon />}
      freeSolo={!!autocompleteOptions}
      getOptionLabel={option => option}
      inputValue={searchInput}
      onClose={handleClear}
      onInputChange={handleChange}
      options={autocompleteOptions}
      renderInput={params => <TextFieldWithAdornment {...params} />}
    />
  );
};

export default SearchField;

TextFieldWithAdornment. js:

import React, { useContext } from 'react';
import SearchIcon from '@material-ui/icons/SearchTwoTone';

import Context from '../../../Context';
import { StyledInputAdornment, StyledTextField } from './styles';

const TextFieldWithAdornment = ({ InputProps, ...restProps }) => {
  const [context, setContext] = useContext(Context);

  const handleBlur = () => {
    setContext({ ...context, autocompleteOptions: [] });
  };

  const startAdornment = (
    <StyledInputAdornment position="start">
      <SearchIcon />
    </StyledInputAdornment>
  );

  return (
    <StyledTextField
      InputProps={{ ...InputProps, startAdornment }}
      onBlur={handleBlur}
      {...restProps}
    />
  );
};

export default TextFieldWithAdornment;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...