React 中的 refs 有什么不好的做法?

IT技术 javascript reactjs refs
2021-05-04 03:59:13

我开始学习 React。不同站点的一些人告诉每个人使用 refs 是一种不好的做法(是的,根本不使用它们)。

它的真正含义是什么?我将它附加到例如子组件(以便我可以访问内部内容)是不是很糟糕?

谢谢!

2个回答

React 要求你思考React的方式,而 refs 是 DOM 的一种后门,你几乎不需要使用它。为了彻底简化,react 的思维方式是,一旦状态发生变化,您就重新渲染依赖于该状态的 UI 的所有组件。React 会确保只更新 DOM 的正确部分,从而使整个事情变得高效并且对你隐藏 DOM(有点)。

例如,如果您的组件承载一个 HTMLInputElement,则在 React 中,您将连接一个事件处理程序来跟踪对输入元素的更改。每当用户键入字符时,事件处理程序都会触发,并且在您的处理程序中,您将使用输入元素的新值更新您的状态。对状态的更改会触发托管组件重新渲染自身,包括具有新值的输入元素。

这就是我的意思

import React from 'react';
import ReactDOM from 'react-dom';

class Example extends React.Component {

    state = {
      inputValue: ""
    }

    handleChange = (e) => {
      this.setState({
        inputValue: e.target.value
      })
    }

    render() {
        const { inputValue } = this.state
        return ( 
          <div>
            /**.. lots of awesome ui **/
            /** an input element **/
            <input value={inputValue} onChange={this.handleChange}} />
            /** ... some more awesome ui **/
          </div>
       )
  }
}


ReactDOM.render( <Example />, document.getElementById("app") );
<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="app">
</div>

请注意,无论何时输入值发生变化,处理程序都会被调用,setState 会被调用,并且组件将完全重新呈现自身。

考虑 refs 通常是不好的做法,因为您可能会倾向于只使用 refs 并按照 JQuery 的方式做事,这不是 React 架构/思维方式的意图。

真正更好地理解它的最好方法是构建更多的 React 应用程序和组件。

嗯......不确定它是否有资格作为答案,但它变得太长而无法发表评论。

假设您有一个仪表板,其中包含显示系统各种状态的小部件。每个小部件都有自己的数据源和自己的控件。也许他们甚至不时刷新。但是,当用户想要查看系统的更新视图时,仪表板级别有一个“刷新”按钮。实现这样的按钮并非易事。

如果您在 Redux 应用程序中 - 您有一个选择 -dispatch('refresh')为所有孩子“伪装” 为了解耦它,每个小部件在加载时注册一个动作,以便父级简单地遍历所有动作并在需要强制刷新时触发它们

在非 Redux/Flux 系统中,或者在更复杂/动态的场景中,这可能是不可能的,或者可能没有那么简单。然后,在复杂性方面,refresh在所有小部件上公开方法然后从父级(或者更确切地说,所有者)访问它可能会更好

class WidgetA extends React.Component {
    refresh() {
        console.log('WidgetA refreshed');
    }

    render() {
      return (
        <h3>WidgetA</h3>
      );
    }
}  

class WidgetB extends React.Component {
    refresh() {
        console.log('WidgetB refreshed');
    }

    render() {
      return (
        <h3>WidgetB</h3>
      );
    }
}  

class Dashboard extends React.Component {
    constructor() {
        super();

        this.onRefresh = this.handleRefresh.bind(this);
        this.onRegister = this.handleRegister.bind(this);
        this.widgets = [];
    }

    handleRegister(widget) {
        this.widgets.push(widget);
    }

    handleRefresh() {
        this.widgets.forEach((widget) => {
            widget.refresh();
        });
    }

    render() {
        return (
            <div>
                <button onClick={this.onRefresh}>Refresh</button>
                <hr />
                <WidgetA ref={this.onRegister} />
                <WidgetB ref={this.onRegister} />
            </div>
        );
    }
}

当然,类似的东西,不那么冗长。

作为旁注,我赞成@skav 的回答,并认为应该避免这些情况。这是一个例外。

代码笔示例