如何在重新渲染期间从道具更新派生状态

时间:2015-08-04 08:56:50

标签: reactjs coffeescript

我有一个组件:

React = require 'react'

module.exports = Toolbar = React.createClass

  proptypes:
    initialUrl: React.PropTypes.string
    onUrlChange: React.PropTypes.func

  getInitialState: ->
    url: @props.initialUrl

  handleUrlChange: (e) ->
    @setState(url: e.target.value)

  handleUrlKeyUp: (e) ->
    if e.which == 13
      e.target.blur()
      if (url = @state.url.trim())? and url isnt @props.initialUrl
        @props.onUrlChange?(url)
        @setState {url}
    if e.which == 27
      @setState {url: @props.initialUrl}



  render: ->
    <div className="component-toolbar clearfix">
      <input type="text" value={@state.url} onChange={@handleUrlChange} onKeyUp={@handleUrlKeyUp}/>
    </div>

该组件的工作方式如下:

  1. 在内部使用initialUrl呈现输入。
  2. 用户可以更改它。
  3. 当用户点击进入时,会触发事件onUrlChange
  4. 当用户点击esc时,@state.url将返回原始值(initialUrl
  5. 到目前为止一切顺利。

    但是当我更改道具或上层组件的状态时,派生initalUrl,那么组件具有相同的状态并且不会被重新渲染。这是因为getInitialState只被调用一次。但是解决这个问题的正确方法是什么?

    谢谢。

1 个答案:

答案 0 :(得分:2)

如果您遵循使用initialValue做出反应的输入方式,那么您当前的代码具有相同的行为。只有重新安装会导致它更改网址。

作为替代方案,如何让父母管理状态,并添加onSubmit事件?

module.exports = Toolbar = React.createClass

  propTypes:
    url: React.PropTypes.string
    onChange: React.PropTypes.func
    onSubmit: React.PropTypes.func
    onReset: React.PropTypes.func

  handleUrlChange: (e) ->
    @props.onChange(e.target.value)

  handleUrlKeyUp: (e) ->
    url = @props.url.trim()
    if e.which == 13
      e.target.blur()
      if url?
        @props.onChange?(url)
        @props.onSubmit?(url)
    if e.which == 27
      @props.onReset()

  render: ->
    <div className="component-toolbar clearfix">
      <input type="text" value={@props.url} onChange={@handleUrlChange} onKeyUp={@handleUrlKeyUp}/>
    </div>

当然这会改变你组件的api,但不要害怕!因为您从一个灵活的无状态组件开始,然后可以将其包装在覆盖90%用例的有状态组件中(例如在es6 / 7中)。

class StatefulToolbar extends React.Component {
  static propTypes = {
    initialUrl: React.PropTypes.string,
    onUrlChange: React.PropTypes.func
  };

  constructor(props){
    super();
    this.state = {url: props.initialUrl};
  }

  render(){
    return (
      <Toolbar 
        value={this.state.url}
        onChange={(url) => this.setState({url})}
        onReset={() => this.setState({url: this.props.initialUrl})}
        onSubmit={(url) => this.props.onUrlChange(url)}
      />
    );
  }
}

如果要根据其他事件控制值更新,则应为该特定情况创建包装器,而不是使Toolbar复杂化。

旁注:propTypes,而不是proptypes。