如何在重新渲染期间从道具更新派生状态
Posted
技术标签:
【中文标题】如何在重新渲染期间从道具更新派生状态【英文标题】:How to update derived state from props during rerender 【发布时间】:2015-10-26 14:19:54 【问题描述】:我有一个组件:
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>
组件的工作方式如下:
-
它在内部呈现带有
initialUrl
的输入。
用户可以更改它。
当用户敲击回车时,触发事件onUrlChange
。
当用户按下 esc 时,@state.url
恢复为原始值 (initialUrl
)
到目前为止一切顺利。
但是当我更改上组件的道具或状态时,从 initalUrl
派生然后组件具有相同的状态并且不会重新渲染。这是因为 getInitialState
只被调用一次。但是解决这个问题的正确方法是什么?
谢谢。
【问题讨论】:
试试componentWillReceiveProps(nextProps)生命周期函数。 是的,这是一个选项。我试过了,没关系,但它看起来有点丑(hacky)。只是想知道什么是正确的方法。我猜这一定是一个常见的问题。 使用 componentWillReceiveProps 是正确的方法。为什么你认为它很hacky? 【参考方案1】:如果您遵循 react 中的输入与 initialValue 一起使用的方式,则您当前的代码具有相同的行为。只有重新挂载会导致它更改 url。
作为替代方案,让父母管理状态并添加 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)
/>
);
如果您想控制基于其他事件的值更新,您应该为该特定情况创建一个包装器,而不是使工具栏变得复杂。
旁注:propTypes,而不是 proptypes。
【讨论】:
以上是关于如何在重新渲染期间从道具更新派生状态的主要内容,如果未能解决你的问题,请参考以下文章
当父组件在 Next.js 应用程序中更新其道具时重新渲染 React 子组件