【问题标题】:React Higher Order Component forces re-render of wrapped componentReact Higher Order Component 强制重新渲染包装的组件
【发布时间】:2016-08-24 10:16:25
【问题描述】:

我正在努力理解如何在高阶组件中正确实现此验证行为。

=============================================

编辑:TLDR:感谢用户 @noa-dev 的出色建议,我在这里创建了一个 React Fiddle:https://jsfiddle.net/8nLumb74/1/ 来显示问题。

简单地说:为什么我的文本框在被这个 HOC 包裹时会失去对编辑的关注?

我做错了什么?

文本框组件:

import React from 'react'

export default React.createClass({
    changeText(e) {
        if (this.props.validate)
            this.props.validate(e.target.value)
        this.props.update(e.target.value)
    },
    componentDidMount() {
        console.log('should only be fired once')
    },
    render() {
        return (<input type="text"
            value={this.props.text}
            onChange={this.changeText} />)
    }
})

验证器组件:

import React from 'react'

export default function (WrappedComponent) {
    const Validation = React.createClass({
        validate(text) {
            console.log('validating', text)
        },
        render() {
            return (
                <WrappedComponent
                {...this.props}
                validate={this.validate}
                />
            )
        }
    })
    return Validation
}

父表单组件:

import React from 'react'
import TextBox from './text-box'
import Validator from './validator'

export default React.createClass({
    getInitialState() {
        return ({text: 'oh hai'})
    },
    update(text) {
        this.setState({text})
    },
    render() {
        const ValidatingTextBox = Validator(TextBox)
        return (<ValidatingTextBox
            text={this.state.text}
            update={this.update} />)
    }
})

【问题讨论】:

  • 我建议您查看 React Native Docs facebook.github.io/react/docs/advanced-performance.html 的高级性能。或者简单地在同一个组件中处理您的验证,以便保持它没有任何重新渲染,并且只将完成的字符串发送到更高阶的组件来存储它。
  • 绝对是一个考虑因素,但目前该应用程序希望任何文本更改(甚至在完成编辑此值之前)来更新全局状态(在这种情况下保存在 redux 中),以便应用程序的其余部分可以显示你“完成后会是什么样子”......
  • 我确信我在高阶组件设置中遗漏了一些明显的东西——即为什么 React 认为它需要拆除整个输入 DOM 元素而不是仅仅更新值字段?
  • 它不会重新绘制整个 DOM 元素,如果您使用 react 的开发人员工具,它们会为您提供更新或重新渲染的 BOX 的视觉突出显示 - 但会按原样作出反应足够聪明,只需替换需要替换的值。它总是比较两个虚拟 DOM,只替换实际发生变化的东西。但是由于该字段的值正在更改,您将始终在输入组件周围看到一个突出显示。我刚刚读到用户失去了对字段的关注 - 这不应该发生......你能准备一个反应小提琴,以便我可以测试它吗?
  • 好的,谢谢... 1. 没有 HOC 和焦点的工作示例不会丢失:jsfiddle.net/qkg328n2

标签: javascript reactjs


【解决方案1】:

Form组件的render方法中,你每次都创建一个新的ValidatingTextBox

    render() {
        const ValidatingTextBox = Validator(TextBox)
        return (<ValidatingTextBox
            text={this.state.text}
            update={this.update} />)
    }

相反,您应该制作组件然后使用它,以便维护实例。一个可能的Form 组件如下所示:

import React from 'react'
import TextBox from './text-box'
import Validator from './validator'

const ValidatingTextBox = Validator(TextBox) 

export default React.createClass({
    getInitialState() {
        return ({text: 'oh hai'})
    },
    update(text) {
        this.setState({text})
    },
    render() {
        return (<ValidatingTextBox
            text={this.state.text}
            update={this.update} />)
    }
})

【讨论】:

  • 所以唯一的问题是我的合成在我的渲染方法中?该死的,我太愚蠢了——感谢 LOADS Davin!
  • 我也面临同样的问题。我需要根据道具选择一个组件。 switch (type) { case "a": componentToBeRendered = FormA; break; case "b": componentToBeRendered = FormB; break; } const FinalComponent = HOC(componentToBeRendered, propsObject); 所以,只要我在输入字段中输入一个字符,表单就会重新呈现。
猜你喜欢
  • 2018-02-25
  • 2018-12-23
  • 1970-01-01
  • 2014-04-20
  • 2017-05-08
  • 2020-10-17
  • 2019-11-12
  • 2018-08-20
  • 2016-12-31
相关资源
最近更新 更多