我在使用React表单并正确管理状态时遇到问题.我在表单中有一个时间输入字段(在模态中).初始值设置为状态变量getInitialState,并从父组件传入.这本身就可以.
当我想通过父组件更新默认的start_time值时,问题出现了.更新本身发生在父组件中setState start_time: new_time.但是在我的表单中,默认的start_time值永远不会改变,因为它只定义一次getInitialState.
我试图用来componentWillUpdate强制改变状态setState start_time: next_props.start_time,这确实有效,但给了我Uncaught RangeError: Maximum call stack size exceeded错误.
所以我的问题是,在这种情况下更新状态的正确方法是什么?我是否以某种方式思考这个错误?
现行代码:
@ModalBody = React.createClass
getInitialState: ->
start_time: @props.start_time.format("HH:mm")
#works but takes long and causes:
#"Uncaught RangeError: Maximum call stack size exceeded"
componentWillUpdate: (next_props, next_state) ->
@setState(start_time: next_props.start_time.format("HH:mm"))
fieldChanged: (fieldName, event) ->
stateUpdate = {}
stateUpdate[fieldName] = event.target.value
@setState(stateUpdate)
render: ->
React.DOM.div
className: "modal-body"
React.DOM.form null,
React.createElement FormLabelInputField,
type: "time"
id: "start_time"
label_name: "Start Time"
value: @state.start_time
onChange: @fieldChanged.bind(null, "start_time”)
@FormLabelInputField = React.createClass
render: ->
React.DOM.div
className: "form-group"
React.DOM.label
htmlFor: @props.id
@props.label_name + ": "
React.DOM.input
className: "form-control"
type: @props.type
id: @props.id
value: @props.value
onChange: @props.onChange
Run Code Online (Sandbox Code Playgroud)
Bra*_*ugh 269
如果我理解正确,你有一个父组件传递start_time给ModalBody组件,它将它分配给自己的状态?并且您希望从父级更新该时间,而不是子组件.
React有一些处理这种情况的技巧.(注意,这是一篇旧文章,已经从网上删除.这是一个关于组件道具的当前文档的链接).
使用道具生成状态
getInitialState通常会导致"真实来源"的重复,即真实数据的位置.这是因为getInitialState仅在首次创建组件时调用.在可能的情况下,即时计算值以确保它们以后不会失去同步并导致维护问题.
基本上,无论何时将父项指定给props子项state,都不会在prop update上调用render方法.您必须使用该componentWillReceiveProps方法手动调用它.
componentWillReceiveProps(nextProps) {
// You don't have to do this check first, but it can help prevent an unneeded render
if (nextProps.startTime !== this.state.startTime) {
this.setState({ startTime: nextProps.startTime });
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ulz 60
显然事情正在改变.... getDerivedStateFromProps()现在是首选功能.
class Component extends React.Component {
static getDerivedStateFromProps(props, current_state) {
if (current_state.value !== props.value) {
return {
value: props.value,
computed_prop: heavy_computation(props.value)
}
}
return null
}
}Run Code Online (Sandbox Code Playgroud)
Luc*_*cia 28
componentWillReceiveProps 正在被弃用,因为使用它"经常会导致错误和不一致".
如果某些内容发生变化,请考虑完全重置子组件key.
为key子组件提供prop可确保无论何时key从外部更改值,都会重新呈现此组件.例如,
<EmailInput
defaultEmail={this.props.user.email}
key={this.props.user.id}
/>
Run Code Online (Sandbox Code Playgroud)
关于它的表现:
虽然这可能听起来很慢,但性能差异通常是微不足道的.如果组件具有在更新上运行的重逻辑,则使用密钥甚至可以更快,因为该子树的绕过被绕过.
arm*_*6er 21
还有componentDidUpdate可用.
功能签名:
componentDidUpdate(prevProps, prevState, snapshot)
Run Code Online (Sandbox Code Playgroud)
将此作为在更新组件时对DOM进行操作的机会.在初始时不会被调用render.
见你可能不需要衍生州的文章,描述反模式两个componentDidUpdate和getDerivedStateFromProps.我发现它非常有用.
小智 7
// store the startTime prop in local state\nconst [startTime, setStartTime] = useState(props.startTime)\n// \nuseEffect(() => {\n if (props.startTime !== startTime) {\n setStartTime(props.startTime);\n }\n}, [props.startTime]);\nRun Code Online (Sandbox Code Playgroud)\n这个方法可以迁移到类components\xef\xbc\x9f吗
\n小智 6
新的挂钩方法是使用useEffect而不是componentWillReceiveProps的旧方法:
componentWillReceiveProps(nextProps) {
// You don't have to do this check first, but it can help prevent an unneeded render
if (nextProps.startTime !== this.state.startTime) {
this.setState({ startTime: nextProps.startTime });
}
}
Run Code Online (Sandbox Code Playgroud)
在功能挂钩驱动的组件中变为以下内容:
// store the startTime prop in local state
const [startTime, setStartTime] = useState(props.startTime)
//
useEffect(() => {
if (props.startTime !== startTime) {
setStartTime(props.startTime);
}
}, [props.startTime]);
Run Code Online (Sandbox Code Playgroud)
我们使用setState设置状态,使用useEffect来检查对指定道具的更改,并采取措施在道具更改时更新状态。
| 归档时间: |
|
| 查看次数: |
190524 次 |
| 最近记录: |