gpt4 book ai didi

javascript - React 初学者问题 : Textfield Losing Focus On Update

转载 作者:行者123 更新时间:2023-11-30 13:57:52 25 4
gpt4 key购买 nike

我编写了一个组件,该组件应该列出一堆带有相应文本字段的复选框。当您单击复选框或在字段中键入内容时,它意味着更新状态。

文本框工作正常,但当我在字段中输入时,它更新状态正常,但每当我点击键盘时我就会失去焦点。

我意识到这可能是因为没有设置键,所以我为所有内容都添加了键,但它仍然失去焦点。有一次我尝试在我的事件中添加 stopPropegation 因为我认为这可能会导致问题?我不确定..仍在学习中...似乎没有用,所以我也删除了那部分。

似乎仍然无法弄清楚是什么导致它失去焦点...有人对此问题有任何建议/解决方案吗?

我合并了我的代码并删除了不必要的部分以使其更易于阅读。有三个相关的 JS 文件..请看下面:

我仍然是初学者/学习者,所以如果您有与此代码的任何部分相关的有用建议,请随时提供。谢谢!

App.js

import React, { Component } from 'react';
import Form from './Form'

class App extends Component {
constructor() {
super();
this.state = {
mediaDeliverables: [
{label: 'badf', checked: false, quantity:''},
{label: 'adfadf', checked: false, quantity:''},
{label: 'adadf', checked: false, quantity:''},
{label: 'addadf', checked: false, quantity:''},
{label: 'adfdes', checked: false, quantity:''},
{label: 'hghdgs', checked: false, quantity:''},
{label: 'srtnf', checked: false, quantity:''},
{label: 'xfthd', checked: false, quantity:''},
{label: 'sbnhrr', checked: false, quantity:''},
{label: 'sfghhh', checked: false, quantity:''},
{label: 'sssddrr', checked: false, quantity:''}
]
}
}

setMediaDeliverable = (value, index) => {
let currentState = this.getStateCopy();
currentState.mediaDeliverables[index] = value;
this.setState(currentState);
}

getStateCopy = () => Object.assign({}, this.state);

render() {
return (
<div className="App">
<Form
key="mainForm"
mediaDeliverablesOptions={this.state.mediaDeliverables}
setMediaDeliverable={this.setMediaDeliverable}
/>
</div>
);
}
}
export default App;

表单.js

import React from 'react';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import FormControl from '@material-ui/core/FormControl';
import FormLabel from '@material-ui/core/FormLabel';
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import MediaDeliverablesCheckBox from './MediaDeliverablesCheckBox';


const useStyles = makeStyles(theme => ({
container: {
display: 'inline-block',
flexWrap: 'wrap',
},
root: {
display: 'inline-block',
flexWrap: 'wrap',
maxWidth: 600,
textAlign: 'left',
},
extendedIcon: {
marginRight: theme.spacing(1),
},
formControl: {
margin: theme.spacing(1),
minWidth: 120,
maxWidth: 300,
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 370,
},
dense: {
marginTop: 19,
},
chips: {
display: 'flex',
flexWrap: 'wrap',
},
chip: {
margin: 2,
},
noLabel: {
marginTop: theme.spacing(3),
},
}));

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};

function getStyles(name, accountName, theme) {
// console.log('>> [form.js] (getStyles) ',accountName)
return {
fontWeight:
accountName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}



export default function Form(props) {

const mediaDeliverablesOptions = props.mediaDeliverablesOptions;
const classes = useStyles();
const theme = useTheme();

const CheckboxGroup = ({ values, label, onChange }) => (
<FormControl component="fieldset">
<FormLabel component="legend">{label}</FormLabel>
<FormGroup>
{values.map((value, index) => (
<FormControlLabel
key={index}
control={
<Checkbox
checked={value.checked}
onChange={onChange(index)}
/>
}
label={value.label}
/>
))}
</FormGroup>
</FormControl>
);

const MediaDeliverableCheckBoxList = ({values, label}) => (
<FormControl component="fieldset">
<FormLabel component="legend">{label}</FormLabel>
<FormGroup>
{values.map((value, index) => (
<MediaDeliverablesCheckBox
key={index}
mediaDeliverablesOptions={value}
onMediaDeliverableChange={onMediaDeliverableChange(index)}
/>
))}
</FormGroup>
</FormControl>
);



const onCheckBoxChange = index => ({ target: { checked } }) => {
const newValues = [...values];
const value = values[index];
newValues[index] = { ...value, checked };
props.setDesignOrDigital(newValues);
};

const onMediaDeliverableChange = index => (deliverableData, e) => {
props.setMediaDeliverable(deliverableData, index);
}

return (
<div className={classes.root}>
<MediaDeliverableCheckBoxList
label="Please Choose Deliverables:"
values={mediaDeliverablesOptions}
key="media-deliverable-checkbox-list"
/>
</div>
);
}

MediaDeliverablesCheckbox.js

import React from 'react';
import Checkbox from '@material-ui/core/Checkbox';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import FormControl from '@material-ui/core/FormControl';
import FormLabel from '@material-ui/core/FormLabel';
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import TextField from '@material-ui/core/TextField';

export default function MediaDeliverablesCheckBox(props) {

let deliverableData = Object.assign({}, props.mediaDeliverablesOptions);

const onCheckBoxChange = (e) => {
deliverableData.checked = e.target.checked;
props.onMediaDeliverableChange(deliverableData, e);
}

const onQuantityChange = (e) => {
deliverableData.quantity = e.target.value;
props.onMediaDeliverableChange(deliverableData, e);
}

const CheckboxGroup = ({ value, label }) => (

<FormControl component="fieldset">
<FormGroup>
<FormControlLabel
control={
<Checkbox
key={props.index}
checked={value.checked}
onChange={onCheckBoxChange}
/>
}
label={label}
/>
</FormGroup>
</FormControl>
);

return(
<div className="MediaDeliverablesCheckBox">
<CheckboxGroup
key={props.index}
label={props.mediaDeliverablesOptions.label}
value={props.mediaDeliverablesOptions}
/>
<TextField
key={'tf'+props.index}
id={'quantity-'+props.index}
label="Quantity"
placeholder="How many do you need?"
multiline
variant="outlined"
value={props.mediaDeliverablesOptions.quantity}
onChange={onQuantityChange}
fullWidth
/>
</div>
);
}

根据 Ryan C 推荐的编辑更新了 Form.js。

import React from 'react';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import FormControl from '@material-ui/core/FormControl';
import FormLabel from '@material-ui/core/FormLabel';
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import MediaDeliverablesCheckBox from './MediaDeliverablesCheckBox';


const useStyles = makeStyles(theme => ({
container: {
display: 'inline-block',
flexWrap: 'wrap',
},
root: {
display: 'inline-block',
flexWrap: 'wrap',
maxWidth: 600,
textAlign: 'left',
},
extendedIcon: {
marginRight: theme.spacing(1),
},
formControl: {
margin: theme.spacing(1),
minWidth: 120,
maxWidth: 300,
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 370,
},
dense: {
marginTop: 19,
},
chips: {
display: 'flex',
flexWrap: 'wrap',
},
chip: {
margin: 2,
},
noLabel: {
marginTop: theme.spacing(3),
},
}));

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};

function getStyles(name, accountName, theme) {
return {
fontWeight:
accountName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}


// Failed to compile
// ./src/Form.js
// Line 86: Parsing error: Unexpected token, expected ","

// 84 |
// 85 | const MediaDeliverableCheckBoxList = ({values, label, onMediaDeliverableChange}) => (
// > 86 | {values.map((value, index) => (
// | ^
// 87 | <MediaDeliverablesCheckBox
// 88 | key={index}
// 89 | index={index}
// This error occurred during the build time and cannot be dismissed.

const MediaDeliverableCheckBoxList = ({values, label, onMediaDeliverableChange}) => (
{values.map((value, index) => (
<MediaDeliverablesCheckBox
key={index}
index={index}
mediaDeliverablesOptions={value}
onMediaDeliverableChange={onMediaDeliverableChange(index)}
/>
))}
);

export default function Form(props) {

const mediaDeliverablesOptions = props.mediaDeliverablesOptions;
const classes = useStyles();
const theme = useTheme();

const CheckboxGroup = ({ values, label, onChange }) => (
<FormControl component="fieldset">
<FormLabel component="legend">{label}</FormLabel>
<FormGroup>
{values.map((value, index) => (
<FormControlLabel
key={index}
control={
<Checkbox
checked={value.checked}
onChange={onChange(index)}
/>
}
label={value.label}
/>
))}
</FormGroup>
</FormControl>
);


const onCheckBoxChange = index => ({ target: { checked } }) => {
const newValues = [...values];
const value = values[index];
newValues[index] = { ...value, checked };
props.setDesignOrDigital(newValues);
};

const onMediaDeliverableChange = index => (deliverableData, e) => {
props.setMediaDeliverable(deliverableData, index);
}

return (
<div className={classes.root}>
<MediaDeliverableCheckBoxList
onMediaDeliverableChange={onMediaDeliverableChange}
/>
</div>
);
}

最佳答案

我看到两个主要问题:

  1. 您如何定义不同的组件(嵌套组件类型)
  2. 不将 index prop 传递给需要它的组件

你有以下结构(省略与我的观点没有直接关系的细节):

export default function Form(props) {

const onMediaDeliverableChange = index => (deliverableData, e) => {
props.setMediaDeliverable(deliverableData, index);
}

const MediaDeliverableCheckBoxList = ({values, label}) => (
<FormGroup>
{values.map((value, index) => (
<MediaDeliverablesCheckBox key={index} onMediaDeliverableChange={onMediaDeliverableChange(index)}/>
))}
</FormGroup>
);

return (
<MediaDeliverableCheckBoxList/>
);
}

函数MediaDeliverableCheckBoxList表示用于呈现 <MediaDeliverableCheckBoxList/> 的组件类型元素。每当Form由于 Prop 或状态改变而重新渲染,React 将重新渲染其子级。如果特定子项的组件类型相同(加上一些其他条件,例如 key 如果指定相同),那么它将更新现有的 DOM 节点。如果特定子项的组件类型不同,则相应的 DOM 节点将被删除,并将新节点添加到 DOM。

通过定义 MediaDeliverableCheckBoxList组件类型 Form功能,您导致该组件类型在每次渲染时都不同。这将导致所有 DOM 节点被替换而不仅仅是更新,这将导致焦点在先前具有焦点的 DOM 节点被移除时消失。它还会导致性能显着下降。

您可以通过将此组件类型移出 Form 来解决此问题函数,然后添加所需的任何其他 Prop (例如 onMediaDeliverableChange )以传达 Form 内部已知的上下文.您还需要将索引作为 Prop 传递给 MediaDeliverablesCheckBox因为它正在使用它。

const MediaDeliverableCheckBoxList = ({values, label, onMediaDeliverableChange}) => (
<FormGroup>
{values.map((value, index) => (
<MediaDeliverablesCheckBox key={index} index={index} onMediaDeliverableChange={onMediaDeliverableChange(index)}/>
))}
</FormGroup>
);


export default function Form(props) {

const onMediaDeliverableChange = index => (deliverableData, e) => {
props.setMediaDeliverable(deliverableData, index);
}


return (
<MediaDeliverableCheckBoxList onMediaDeliverableChange={onMediaDeliverableChange}/>
);
}

您对 CheckboxGroup 也有同样的问题可能还有其他组件。

关于javascript - React 初学者问题 : Textfield Losing Focus On Update,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56873912/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com