简体   繁体   English

(React、MaterialUI、Context)MUI 自动完成/TextField 未在挂载时呈现其值

[英](React, MaterialUI, Context) MUI Autocomplete/TextField not rendering it's value on mount

I'm using Material UI's Autocomplete component in conjunction with their TextField component.我将 Material UI 的 Autocomplete 组件与他们的 TextField 组件结合使用。 Everything's working as expected with the exception of one issue.除了一个问题外,一切都按预期工作。 The TextField is not rendering its input value on mount. TextField 未在安装时呈现其输入值。 I checked that it's receiving the value, it just won't show for some reason.我检查了它是否收到了价值,但由于某种原因它不会显示。

The functionality I'm going for is to have the form inputs hold their values even when unmounted/mounted - so long as the root App component stays mounted.我要实现的功能是让表单输入即使在卸载/安装时也保持其值 - 只要根 App 组件保持安装状态。 The state for the form lives at the top level of the app in Context.表单的 state 位于 Context 中应用程序的顶层。 The form has the search field I mentioned, an MUI Select component, and submit button.该表单具有我提到的搜索字段、MUI Select 组件和提交按钮。 I'm doing the same thing with the Select component and that's working fine, just not the Autocomplete/TextField.我正在用 Select 组件做同样的事情,这工作正常,只是不是自动完成/文本字段。 Is this issue related to Autocomplete specifically?这个问题是否与自动完成特别相关?

Context.js:上下文.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: 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: 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:队列选择.js:
(this is working) (这是工作)

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;

I just figured this out.我刚刚想通了。 I had the TextField as the controlled form component being passed the onChange & value props.我将 TextField 作为受控表单组件,传递了 onChange 和 value 道具。 I needed the Autocomplete to be controlled instead, making use of the 'onInputChange' and 'inputValue' props.我需要使用“onInputChange”和“inputValue”道具来控制自动完成功能。

SearchField.js: 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: 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;

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

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