响应输入onChange滞后

use*_*353 13 reactjs

我有一个带有onChange事件处理程序的简单控制输入.

一切都按照handleChange每次按键点火的方式工作,问题是它很慢.

使用输入时存在非常明显的延迟.是否有一些额外的代码我必须正常工作才能正常输入?

我是否必须去除输入?

据我所知,在文档中没有提到这个问题,我不知道是否还有一些额外的事情需要做,或者我是否onChange错误地使用了回调.

handleChange = (event) => {
    this.setState({ itemNumber: event.target.value })
  }


<TextField
      id="Part #"
      label="Part #"
      value={this.state.itemNumber}
      onChange={this.handleChange}
      margin="normal"
    />
Run Code Online (Sandbox Code Playgroud)

组件:

export class Dashboard extends Component {
  state = {
    report: '',
    selectedDate: new Date(),
    itemNumber: '',
  }

  static propTypes = {
    classes: object,
    headerTitle: string,
    userInfo: object,
  }

  static defaultProps = {
    classes: {},
    headerTitle: undefined,
    userInfo: {},
  }

  reportSelected = (event) => {
    this.setState(() => {
      return {
        report: event.target.value,
      }
    })
  }

  handleDateChange = (date) => {
    this.setState({ selectedDate: new Date(date) })
  }

  handleChange = (event) => {
    this.setState({ itemNumber: event.target.value })
  }

  render () {
    const { classes, headerTitle, userInfo } = this.props
    return (
      <div className={classes.dashboard}>
        <HeaderTitle title="Dashboard" />
        <Helmet>
          <title>{headerTitle}</title>
        </Helmet>

        { userInfo.isAuthorized &&
          <Grid container direction={'row'} justify={'center'} className={classes.formContainer}>
            <Grid item xs={12} sm={12} md={12} lg={6} xl={5}>
              <form className={classes.form}>
                <FormControl className={classes.presetReportsInput}>
                  <InputLabel htmlFor="reports">Preset Reports</InputLabel>
                  <Select
                    value={this.state.report}
                    onChange={this.reportSelected}
                  >
                    <MenuItem value="">
                      <em>None</em>
                    </MenuItem>
                    {presetReports.getReportList().map(report => (
                      <MenuItem value={report.name} key={report.name}>
                        {report.name}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>

                { (this.state.report === 'Inventory Snapshot' ||
                   this.state.report === 'Weekly Fill Rate' ||
                   this.state.report === 'Open Orders' ||
                   this.state.report === 'Weekly Shipments') &&
                   <div>
                     <Grid container spacing={8} direction={'row'}>
                       <Grid item>
                         <MuiPickersUtilsProvider utils={MomentUtils}>
                           <DatePicker
                             className={classes.datePicker}
                             margin="normal"
                             keyboard
                             format="DD/MM/YYYY"
                             disableFuture
                             autoOk
                             mask={value => (value ? [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/] : [])}
                             value={this.state.selectedDate}
                             onChange={this.handleDateChange}
                             disableOpenOnEnter
                             animateYearScrolling={false}
                           />
                         </MuiPickersUtilsProvider>
                       </Grid>

                       <Grid item>
                         <TextField
                           id="Part #"
                           label="Part #"
                           value={this.state.itemNumber}
                           onChange={this.handleChange}
                           margin="normal"
                         />
                       </Grid>
                     </Grid>

                     <Button variant="raised" color="primary" style={{ marginTop: 10 }}>
                       Search
                     </Button>
                   </div>
                }

                { this.state.report === '' &&
                  <div>
                    <TextField
                      id="queryField"
                      label="Run a Query"
                      className={classes.queryField}
                      helperText=""
                      margin="normal"
                      multiline
                      rows="5"
                    />

                    <Grid container direction={'row'} justify={'flex-end'}>
                      <Grid item>
                        <Button variant="raised" color="primary">
                          Export
                        </Button>
                      </Grid>
                      <Grid item>
                        <Button variant="raised" color="primary">
                          Save Query
                        </Button>
                      </Grid>
                    </Grid>
                  </div>
                }
              </form>
            </Grid>

            { this.state.report === 'Inventory Snapshot' &&
              <Grid container className={classes.table}>
                <Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
                  <InventoryReport />
                </Grid>
              </Grid>
            }
          </Grid>
        }
      </div>
    )
  }
}

const styles = {
  dashboard: {},
  formContainer: {
    margin: 0,
    width: '100%',
  },
  presetReportsInput: {
    width: '100%',
    margin: '20% 0 0 0',
  },
  queryField: {
    width: '100%',
    margin: '20% 0 0 0',
  },
  table: {
    margin: '50px 0 10px 0',
  },
  datePicker: {
    marginTop: 32,
  },
}

const mapStateToProps = state => {
  const { layout } = state
  const { headerTitle } = layout
  return {
    headerTitle: headerTitle,
  }
}

export default connect(mapStateToProps)(withStyles(styles)(Dashboard))
Run Code Online (Sandbox Code Playgroud)

我正在观看chrome中的devtools的状态更新,并且输入的字符和状态更新之间至少有500毫秒的延迟,更快的打字速度要长得多.为什么setState这么慢?使此表单行为像普通Web表单一样的解决方法是什么?

ᴘᴀɴ*_*ᴛɪs 22

setState它本身并不慢,只有当你的渲染变得非常昂贵时它才开始引起问题.

需要考虑的一些事项是:

  • 您的主要组件看起来非常大,并且在每次击键时都会重新渲染,因此可能会导致性能问题.尝试将其分解为更小的组件.
  • 确保在render主组件的方法中呈现的子组件不会被不必要地重新呈现.为什么你更新可以指出那些不必要的重新渲染.切换到PureComponent无状态组件或使用shouldComponentUpdate可以提供帮助.
  • 虽然你不能避免在这里重新渲染(因为你的表单输入需要用新的状态值重新渲染),通过分解成更小的组件,你可以使用shouldComponentUpdate让React知道组件的输出是否不受当前更改的影响陈述或道具,避免不必要的重新渲染.
  • 切换到生产版本以获得更好的性能
  • 切换到不受控制的组件,让DOM自己处理输入组件(这是您描述的"正常Web表单"行为).当您需要访问表单的值时,您可以使用ref's'来访问底层DOM节点并直接读取它们的值.这应该消除呼叫的需要setState,因此不需要重新渲染


Sud*_*mar 15

对于大型表单来说,当一个输入的更改触发整个组件重新渲染时,这尤其是一个问题,在 redux 中也是如此,尽管 redux 似乎不会干扰这里。

如果您希望您的输入受到控制并具有相同的行为,那么您始终可以这样做

<input
  className="form-control"
  type="text"
  name="name"
  value={form.name}
  onBlur={onChangeHandler}
/>
Run Code Online (Sandbox Code Playgroud)

这只会触发模糊事件并防止每次更改时重新渲染。它很有用,因为当您单击任何其他按钮来处理数据时,可以保证您将拥有更新的状态。如果您的逻辑需要与输入数据相关的即时验证/处理,这将没有帮助。

另外,我应该提到的是,有时这无法与非 HTML5 原生的其他组件一起使用,因为它们可能会阻止基于 value 属性的重新渲染

注意:请在此处阅读 onBlur 事件

  • 这不适用于 MUI 组件:( (3认同)

小智 13

这可能看起来像是一个微不足道的响应,但 \xe2\x80\x94 确保你的控制台已关闭。当控制台打开时,受控组件有明显的滞后!

\n