简体   繁体   English

React + Redux - 当输入具有来自状态的值时,输入 onChange 非常慢

[英]React + Redux - Input onChange is very slow when typing in when the input have a value from the state

I got my input who is filled by a value from my state.我得到了我的输入,该输入由我所在州的值填充。

<input id="flashVars" name="flashVars" type="text" value={settings.flashVarsValue} disabled={isDisabled} onChange={handleChange} />

Settings is my state with Redux. Settings是我对 Redux 的状态。 When i put a value into my input, i must specify a onChange function.当我将一个值放入我的输入时,我必须指定一个onChange函数。 This is my onChange function:这是我的 onChange 函数:

handleFlashVarsChange(e) {
  let { dispatch } = this.props;

  dispatch( changeFlashVarsValue(e.target.value) );
}

It change the state value flashVarsValue for the value of the input.它更改输入值的状态值flashVarsValue But when i type in my input, it lags.但是当我输入我的输入时,它会滞后。 I don't understand why i should call the dispatch each time i change the input value.我不明白为什么每次更改输入值时都要调用调度程序。

Is there any way who can give less lags?有什么办法可以减少滞后吗?

My reducer:我的减速机:

import { ACTIONS } from '../utils/consts';

const initialState = {
  ...
  flashVarsValue: '',
  ...
};

export function formSettings(state = initialState, action = '') {
  switch (action.type) {

    ...

    case ACTIONS.CHANGE_FLASHVARS_VALUE:
      return Object.assign({}, state, {
        flashVarsValue: action.data
      });

    default:
      return state;
  }
}

My action:我的行动:

export function changeFlashVarsValue(data) {
  return {
    type: ACTIONS.CHANGE_FLASHVARS_VALUE,
    data: data
  }
}

Thank you谢谢

I had a similar problem when I was editing a grid with a million rows, so what I did was to change the update logic, in your case handleChange to be called only on the event onBlur instead of onChange .我在编辑具有一百万行的网格时遇到了类似的问题,因此我所做的是更改更新逻辑,在您的情况下,仅在onBlur而不是onChange事件上调用handleChange This will only trigger the update when you lose focus.这只会在您失去焦点时触发更新。 But don't know if this would be a satisfactory solution for you.但不知道这对你来说是否是一个令人满意的解决方案。

The answer for me was to use the shouldComponentUpdate lifecycle hook.我的答案是使用 shouldComponentUpdate 生命周期钩子。 This has already been given as an answer in a comment by Mike Boutin (about a year ago :) ), but an example might help the next visitor here.这已经在 Mike Boutin(大约一年前 :) )的评论中作为答案给出,但一个例子可能会帮助下一位访问者。

I had a similar problem, with the text input being lost, and slow and jumpy.我有一个类似的问题,文本输入丢失,并且缓慢而跳跃。 I was using setState to update the formData in my onChange event.我在 onChange 事件中使用 setState 更新 formData。

I found that the form was doing a complete re-render with every keypress, as the state had changed.我发现表单在每次按键时都进行了完整的重新渲染,因为状态发生了变化。 So to stop this, I overrode the function:因此,为了阻止这种情况,我覆盖了该功能:

shouldComponentUpdate(nextProps, nextState) {
   return this.state.formErrors !== nextState.formErrors);
}

I show an error notification panel on form submission with any new or changed validation errors, and that's the only time I need to re-render.我在表单提交时显示一个错误通知面板,其中包含任何新的或更改的验证错误,这是我唯一需要重新呈现的时间。

If you have no child components, you could probably just set the form component's shouldComponentUpdate to always return false.如果您没有子组件,您可能只需将表单组件的 shouldComponentUpdate 设置为始终返回 false。

I know this is an old question, but if you want to fire onChange on a text input, you probably want to debounce your event.我知道这是一个老问题,但是如果您想在文本输入上触发 onChange,您可能希望对您的事件进行去抖动。 This thread does a good job breaking it down, but I think this would work for the op's example: 该线程在分解它方面做得很好,但我认为这适用于操作示例:

import debounce from 'debounce'                                      

function debounceEventHandler(...args) {
  const debounced = debounce(...args)
  return function (e) {
    e.persist();
    return debounced(e);
  }
}                                                                      
const Container = React.createClass({
  handleFlashVarsChange(e) {
    let { dispatch } = this.props;
    //basic redux stuff
    this.props.changeFlashVarsValue(e.target.value));
  },
  render() {
    const handleChange = debounceEventHandler(this.handleFlashVarsChange, 15);
    return (
      <input id="flashVars" onChange={handleChange} />
    )
  }                                                                         
}
//...prep and return your redux container

The issue here is possibly re-renders.这里的问题可能是重新渲染。 You're passing in "settings" (your entire state) to your component containing the "input", and we don't know how the rest of your connected components are coupled to state.您将“设置”(您的整个状态)传递给包含“输入”的组件,我们不知道其余连接的组件如何与状态耦合。 Check to see if as a result of the state object mutating, you're rerendering much more than just the input on every keystroke.检查是否由于状态对象发生变异,您重新渲染的不仅仅是每次击键时的输入。 The solution to this is to more directly pass in the specific parts of state you need from mapStateToProps (in this case, maybe only pass in "flashVarsValue" if that's all this component needs, and make sure other components aren't also passed the whole state) and use PureRenderMixin or Dan Abramov's https://github.com/gaearon/react-pure-render if you're using ES6 components to not re-render if your props haven't changed对此的解决方案是更直接地从 mapStateToProps 传入您需要的特定状态部分(在这种情况下,如果这就是该组件需要的全部内容,则可能只传入“flashVarsValue”,并确保其他组件也没有通过整个state) 并使用 PureRenderMixin 或 Dan Abramov 的https://github.com/gaearon/react-pure-render如果你使用 ES6 组件,如果你的道具没有改变就不要重新渲染

The answer is not to re-render your component on every key stroke, only if user stops typing in. Something like this:答案是不要在每次击键时重新渲染你的组件,只有在用户停止输入时才重新渲染。像这样:

shouldComponentUpdate(nextProps, nextState) {
    if (!textInputReRender)
        return false;
    else
        return true;
}

onTextInputChange = (propName, propValue) => {
    if (inputChangeTimerId)
        clearTimeout(inputChangeTimerId);

    inputChangeTimerId = setTimeout(() => {
        inputChangeTimerId = null;
        const newState = {};

        textInputReRender = true;

        newState[propName] = propValue;
        this.setState(newState);
    }, 500);

    textInputReRender = false;
}

Use onChangeText instead改用onChangeText

import { TextInput, View} from "react-native";  
import { connect } from "react-redux"; 
import React, { Component, useState } from "react";

function SearchTextInput(props) {
  const { keyword = "", setKeyword } = props; 
  return (
     <TextInput
       style={styles.searchInputText}
       placeholder={"placeholder here"}
       value={keyword}
       onChangeText={setKeyword(t)}
     />
  );
}

const mapStateToProps = state => {
  return {
    keyword: state.search.keyword,
    search: state.search
  };
};
const mapDispatchToProps = dispatch => ({
  setKeyword: payload => dispatch(({type:'updateSearchText', keyword: payload }))
});
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(SearchTextInput);

The problem is common happen when you have a complex page, that need re-render always that you update the state.当你有一个复杂的页面时,这个问题很常见,需要重新渲染你更新状态。 So you can percept that is very slow when typing.所以你可以感觉到打字时很慢。

I found a solution: The cycle of life of react run by component.我找到了一个解决方案:React 的生命周期由组件运行。 So you can create other component and manage yours events, like onChange, after you can call onBlur, that is passed by props for him.所以你可以创建其他组件并管理你的事件,比如 onChange,在你可以调用 onBlur 之后,由 props 为他传递。 It worked for me:它对我有用:

import React, {Fragment, useState, useEffect} from 'react';
import TextField from '@material-ui/core/TextField';


export function InputText(props) {
  const [value, setValue] = useState("");
  const {onBlur = (e) => {console.log(e)}, name='name', defaultValue= 'Default', type='text', label='Label'} = props

  useEffect(() => {

    // console.log(value);
  })

  return (
      <label>
        <TextField 
          name={name} 
          label={label}  
          onBlur={e => onBlur(e)}
          type={type}
          value={value}
          onChange={e => setValue(e.target.value)}
        />
      </label>
  );
}


class Sample extends React.Component {
    handleBlurInput = e => {        
         this.setState({ [e.target.name]: e.target.value });
    };
  render() {
    return (
    <InputText name="nome" label="Label Sample" defaultValue={this.state.nome} onBlur={this.handleBlurInput.bind(this)} />

    // Complex app ....
    );
  }
}

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

相关问题 打字时表单输入很慢/延迟 - Form input very slow / delayed when typing 当React + Redux上的状态改变时,输入值没有改变 - Value on Input didnt change when state change on React + Redux 输入的onChange React JS使得输入渲染变慢 - onChange for input React JS makes typing render slow 反应:以编程方式更改选中的 state 时在复选框输入上触发 onChange? - React: trigger onChange on checkbox input when changing checked state programmatically? Redux:使用输入 onChange 更改 state - Redux: Change state with input onChange 当 select 选项改变 (onChange) 时,react-select 清除其他输入字段的值(状态) - React-select clears the value (state) of the other input fields when select option is changed (onChange) 反应:如果输入值因状态而变化,则触发 onChange? - React: trigger onChange if input value is changing by state? 当我尝试输入时,React Js 输入失去焦点,但仅在添加 onChange 时 - React Js input is losing focus when I try typing in it but only when onChange is added 在处理来自输入的 onChange 事件时如何获取当前的 state? - How to get the current state when processing the onChange event from an input? 在输入元素上键入时,我的状态未更新 - My state is not updating when typing on the input element
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM