使用react / redux

时间:2017-04-30 17:38:14

标签: javascript reactjs redux lodash

我正试图用react / redux去掉textarea值,并在div#preview中显示去抖动的值,但是在第一次函数调用后我得到了合成事件警告。

我有用于处理textarea值状态的reducer,它正在按预期工作,但为了简单起见,我在这个片段中编写了本地状态。

如果除了debounce之外还有一种更好的方法可以避免在keypress每个class TextArea extends React.Component { constructor(props){ super(props); this.state = {foo: ''} } handleInputChange = _.debounce((e) => { e.persist(); let value = e.target.value; this.setState({foo: value}); }, 300); render() { return ( <div> <textarea onChange={(e)=>this.handleInputChange(e)} value={this.state.foo}></textarea> <p id="preview">{this.state.foo}</p> </div> ); } } ReactDOM.render( <TextArea />, document.getElementById("react") );后反应重新呈现,我很想知道。提前谢谢。

<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
{  
   "something":{  
      "a":"b"
   },
   "some_other_thing":{  
      "c":"d"
   },
   "what_i_want":{  
      "is_down_here":[  
         {  
            "some":{  
               "not_needed":"object"
            },
            "another":{  
               "also_not_needed":"object"
            },
            "i_look_for":"this_tag",
            "tag_properties":{  
               "this":"that"
            }
         },
         {  
            "but_not":{  
               "down":"here"
            }
         }
      ]
   }
}

3 个答案:

答案 0 :(得分:2)

您收到此错误是因为您在.persist()超时内尝试debounce事件。超时调用回调时,合成事件已经释放。所以你必须在辩护之外坚持这个事件。

然而,你的想法有另一个问题。由于文本框是受控组件,因此对更新后的值进行去抖动将导致文本框仅在使用的已停止键入后呈现(部分)文本。

要防止您需要立即更新受控元素的状态,并取消显示状态(或redux操作调度)的更新。

例如:

class TextArea extends React.Component {
  constructor(props){
    super(props);
    this.state = { foo: '', controlled: '' }
  }
  
  updateFoo = _.debounce((value) => { // this can also dispatch a redux action
    this.setState({foo: value});
  }, 300);
  
  handleInputChange = (e) => {
    const value = e.target.value;
    
    this.setState({
      controlled: value
    });
    
    this.updateFoo(value);
  }

  render() {
    return (
      <div>
       <textarea onChange={ this.handleInputChange }
       value={this.state.controlled} />
       <p id="preview">{this.state.foo}</p>
      </div>
    );
  }
}


ReactDOM.render(
  <TextArea />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="react"></div>

答案 1 :(得分:0)

另一个答案已经涵盖了持续活动的问题。对于输入debouncing方面,您可能需要阅读我的博文Practical Redux, Part 7: Form Change Handling。在那篇文章中,我展示了一个可重用的组件,它可以处理应用程序其余部分的debouncing文本输入更新,同时允许它们立即使用当前值重新呈现。

答案 2 :(得分:0)

我在这方面挣扎了很多,无法自己取得令人满意的结果。最终,我使用了 https://github.com/nkbt/react-debounce-input,它运行良好,而且比我之前失败的尝试要简单得多。

  /**
   * Updates the current node "text" value.
   *
   * @param event
   */
  const onTextInputValueChange = (event: any) => {
    const newValue = event.target.value;
    patchCurrentNode({
      data: {
        text: newValue,
      },
    } as InformationNodeData);
  };
    

  <DebounceInput
          element={'textarea'}
          debounceTimeout={500}
          placeholder={'Say something here'}
          onChange={onTextInputValueChange}
          value={node?.data?.text}
        />

patchCurrentNode 写入我的 Recoil 存储。

DebounceInput 组件处理内部状态以显示最新值,而仅偶尔更新存储中的值。

实现并不特定于 Recoil,使用 Redux 可能会像魅力一样工作。