在使用Material-UI v4.11.0的React v16.13.1中,我具有以下组件
const GuestSignup = (props: GuestSignupProps) => {
return <Grid container spacing={1} alignItems="flex-end">
<Grid item xs={1}>
<Tooltip title="Uncheck to cancel individual signup" arrow>
<FormControl>
<FormControlLabel
control={<Checkbox key="ck1" onChange={props.handleSignupCheckChangeGuest(props.gs.guestSignupID === global.NULL_ID ? props.gs.index : props.gs.guestSignupID)} value={props.gs.guestSignupID} checked={props.gs.selected} />}
label=""
/>
</FormControl>
</Tooltip>
</Grid>
<Grid item xs={2}>
<TextField label="First Name" value={props.gs.firstName} key={props.gs.guestSignupID.toString() + 'fn'} required onChange={props.handleFirstNameChange(props.gs.guestSignupID, props.gs.index)} />
</Grid>
<Grid item xs={2}>
<TextField label="Last Name" value={props.gs.lastName} key={props.gs.guestSignupID.toString() + 'ln'} required onChange={props.handleLastNameChange(props.gs.guestSignupID, props.gs.index)} />
</Grid>
<Grid item xs={2}>
<GuestTypes value={props.gs.guestType.guestTypeID} key="gt" gt={props.gt} handleGuestTypeChange={props.handleGuestTypeChange(props.gs.guestSignupID, props.gs.index)} />
</Grid>
<Grid item xs={2}>
<KeyboardDatePicker
autoOk
className={classes.guestDate}
disablePast
disableToolbar
variant="inline"
format="MM/dd/yyyy"
key="ad"
margin="dense"
label="Arrival"
required
value={props.gs.arrivalDate === global.EMPTY_STRING ? null : new Date(props.gs.arrivalDate)}
onChange={props.handleArrivalDateChange(props.gs.guestSignupID === global.NULL_ID ? props.gs.index : props.gs.guestSignupID, GUEST_SIGNUP)}
KeyboardButtonProps={{
'aria-label': 'change date',
}}
/>
</Grid>
<Grid item xs={2}>
<KeyboardDatePicker
autoOk
className={classes.guestDate}
disablePast
disableToolbar
variant="inline"
format="MM/dd/yyyy"
key="dd"
margin="dense"
label="Departure"
required
value={props.gs.departureDate === global.EMPTY_STRING ? null : new Date(props.gs.departureDate)}
onChange={props.handleDepartureDateChange(props.gs.guestSignupID === global.NULL_ID ? props.gs.index : props.gs.guestSignupID, GUEST_SIGNUP)}
KeyboardButtonProps={{
'aria-label': 'change date',
}}
/>
</Grid>
</Grid>
}
使用这些输入道具
interface GuestSignupProps {
id: number;
key: number;
gs: GuestSignup;
gt: Array<GuestType>;
handleArrivalDateChange(id: number, type: string): (date: Date | null) => void;
handleDepartureDateChange(id: number, type: string): (date: Date | null) => void;
handleFirstNameChange(id: number, index: number): (event: React.ChangeEvent<HTMLInputElement>) => void;
handleGuestTypeChange(id: number, index: number): (event: React.ChangeEvent<{ value: unknown }>) => void;
handleLastNameChange(id: number, index: number): (event: React.ChangeEvent<HTMLInputElement>) => void;
handleSignupCheckChangeGuest(id: number): (event: React.ChangeEvent<HTMLInputElement>) => void;
}
使用此数据结构
export interface GuestSignup {
guestSignupID: number;
index: number;
signupID: number;
firstName: string;
lastName: string;
gender: string;
guestType: GuestType;
arrivalDate: string;
departureDate: string;
cancelDate: string;
notes: string;
cancel: boolean;
selected: boolean;
}
状态存储为多个实例的数组
const [guestSignups, setGuestSignups] = React.useState<Array<GuestSignup>>([]);
并呈现为页面中有多个GuestSignup实例的情况。
{guestSignups.length > 0 &&
<React.Fragment>
{
guestSignups.map((gs: GuestSignup, index: number) => (
<GuestSignup id={gs.guestSignupID} key={gs.guestSignupID > 0 ? gs.guestSignupID : index} gs={gs} gt={guestTypes} handleArrivalDateChange={handleArrivalDateChange} handleDepartureDateChange={handleDepartureDateChange} handleFirstNameChange={handleFirstNameChange} handleGuestTypeChange={handleGuestTypeChange} handleLastNameChange={handleLastNameChange} handleSignupCheckChangeGuest={handleSignupCheckChangeGuest} />
))
}
</React.Fragment>
}
名字和姓氏都有处理程序,在每次击键的onChange中都会调用该处理程序
const handleFirstNameChange = (id: number, index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {
// Used either GuestSignupID for existing guests or array index for new guests
const newGuestSignup = produce(guestSignups,
draft => {
const i = draft.findIndex(gs => { return gs.guestSignupID > 0 ? gs.guestSignupID === id : gs.index === index });
draft[i].firstName = event.target.value;
}
);
setGuestSignups([ ...newGuestSignup ]);
}
问题在于,每次按键后,名字和姓氏文本输入都会失去焦点。他们在同胞之间有唯一的钥匙。似乎在处理程序之后重新渲染了整个来宾注册集,因为如果您按下TAB键,则最顶部来宾注册的第一个复选框将获得焦点。
什么是使文本输入元素在每次击键后保持焦点的正确方法?
答案 0 :(得分:0)
几个月前,我也遇到了同样的问题。您需要从所有 TextField 标记中删除 key 属性。如果添加 key 属性,如果key更改并且您的输入将失去焦点,React将重新渲染组件。您可以从here了解有关key的更多信息。