我正在使用 MUI 库来创建我的 React Js 应用程序。
这里我使用受控文本字段组件来创建一个简单的搜索 UI。
但是有一些奇怪的事情。
Text Field
组件在其值更改后失去焦点。
这是我第一次遇到这个问题。我以前从未遇到过这个问题。
这怎么可能发生?还有解决办法是什么。
这是代码和游乐场:https://codesandbox.io/s/mui-autocomplete-lost-focus-oenoo?
注意:如果我从代码中删除
breakpoint type
,则 Text Field
组件在其值更改后仍然会失去焦点。
这是因为您在另一个组件中定义了一个组件,因此每次渲染组件时都会重新创建组件定义(并且每次用户在输入中键入时都会渲染您的组件)。
两种解决方案:
不要将其作为一个单独的组件。
代替:
const MyComponent = () => {
const MyInput = () => <div><input /></div>; // you get the idea
return (
<div>
<MyInput />
</div>
);
};
做:
const MyComponent = () => {
return (
<div>
<div><input /></div> {/* you get the idea */}
</div>
);
};
在其父组件之外定义组件:
const MyInput = ({value, onChange}) => (
<div>
<input value={value} onChange={onChange} />
</div>
);
const MyComponent = () => {
const [value, setValue] = useState('');
return (
<div>
<MyInput
value={value}
onChange={event => setValue(event.target.value)}
/>
</div>
);
};
请注意组件的按键,如果将动态值设置为按键道具,也会导致焦点丢失。这是一个例子
{people.map(person => (
<div key={person.name}>
<Input type="text" value={person.name} onChange={// function which manipulates person name} />
</div>
))}
适用于MUI V5
将自定义样式的代码移到组件之外
例如:
import React from 'react';
import { useTheme, TextField, styled } from '@mui/material';
import { SearchOutlined } from '@mui/icons-material';
interface SearchInputProps { placeholder?: string; onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; value: string; dataTest?: string; }
const StyledSearchInput = styled(TextField)(({ theme }: any) => { return {
'& .MuiOutlinedInput-root': {
borderRadius: '0.625rem',
fontSize: '1rem',
'& fieldset': {
borderColor: `${theme.palette.text.secondary}`
},
'&.Mui-focused fieldset': {
borderColor: `${theme.palette.primary}`
}
} }; });
const SearchInput: React.FC<SearchInputProps> = ({ placeholder = 'Search...', onChange, value, dataTest, ...props }) => { const theme = useTheme();
return (
<StyledSearchInput
{...props}
onChange={onChange}
placeholder={placeholder}
variant="outlined"
value={value}
inputProps={{ 'data-testid': dataTest ? dataTest : 'search-input' }}
InputProps={{
startAdornment: (
<SearchOutlined
sx={{ color: theme.palette.text.secondary, height: '1.5rem', width: '1.5rem' }}
/>
)
}}
/> ); };
export default SearchInput;
谈话有点晚了。但是,添加SchemeSonic的答案,如果您有“动态”组件键,您将其传递给一个组件,该组件为了参数的缘故而呈现一个输入字段列表,并且您希望在特定的输入字段出现时关注它Mounted 后,您可以使用 ref 来存储输入字段 id 到 onMount 回调的映射。
然后,挂载后您可以设置超时来调用 onMount 回调。 这样,您可以在安装组件时专注于该组件(或使用输入引用执行任何操作)。
<InputFieldList
inputFieldIds={inputFieldIds}
renderInputField={(id) => (
<StyledTextField
key={id}
label={id}
variant="outlined"
size="small"
inputRef={id === fieldToFocus ? fieldToFocusRef : undefined}
value={values[id]}
onChange={handleChange(id)}
/>
)}
onMount={(id) => {
// Focus on the input field when it is mounted
if (id === fieldToFocus) fieldToFocusRef.current?.focus();
}}
/>
使用重点道具
<TextField
focused={field.value && true}
/>
修复非常简单
返回(
search value: "${search}"
}
);
只需用 Fragments 包裹动态元素即可。