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

问题描述 投票:38回答:5

我的输入是由我的州的一个值填充的。

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

Settingsis我的Redux状态。当我在输入中放入一个值时,我必须指定一个onChange函数。这是我的onChange函数:

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

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

它将状态值flashVarsValue更改为输入值。但是当我输入我的输入时,它会滞后。我不明白为什么每次改变输入值都应该调用调度。

有什么方法可以减少滞后吗?

我的减速机:

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;
  }
}

我的行动:

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

谢谢

javascript reactjs redux
5个回答
14
投票

当我编辑一个有一百万行的网格时,我遇到了类似的问题,所以我所做的就是更改更新逻辑,在你的情况下,handleChange仅在事件'onBlur'而不是onChange上调用。这只会在您失去焦点时触发更新。但不知道这对你来说是否是一个令人满意的解决方案..


4
投票

这里的问题可能是重新渲染。您将“设置”(整个州)传递给包含“输入”的组件,我们不知道其他连接组件如何与状态耦合。检查是否由于状态对象发生变异,您重新渲染的不仅仅是每次击键时的输入。解决这个问题的方法是从mapStateToProps更直接传递你需要的状态的特定部分(在这种情况下,如果这是所有这个组件需要的话,可能只传递“flashVarsValue”,并确保其他组件也不会传递给整个如果你使用ES6组件不重新渲染,如果你的道具没有改变,请使用PureRenderMixin或Dan Abramov的https://github.com/gaearon/react-pure-render


4
投票

我的答案是使用shouldComponentUpdate生命周期钩子。这已经在Mike Boutin的评论中得到了答案(大约一年前:)),但是一个例子可能会帮助下一位访客。

我有一个类似的问题,文本输入丢失,缓慢和跳跃。我正在使用setState来更新onChange事件中的formData。

我发现,随着状态发生变化,表单正在对每个按键执行完全重新渲染。所以为了阻止这个,我重写了这个功能:

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

我在表单提交时显示错误通知面板,其中包含任何新的或更改的验证错误,这是我需要重新呈现的唯一时间。

如果没有子组件,则可能只需将表单组件的shouldComponentUpdate设置为始终返回false。


3
投票

答案不是在每次击键时重新渲染你的组件,只有当用户停止输入时。这样的事情:

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;
}

2
投票

我知道这是一个古老的问题,但是如果你想在文本输入上触发改变,你可能想要去除你的事件。 This thread做得很好,但是我觉得这对于op的例子很有用:

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
© www.soinside.com 2019 - 2024. All rights reserved.