简体   繁体   English

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

[英]What's a bad practice with refs in React?

I'm getting to learn React. 我正在学习React。 Some guys of different sites tells everyone that using refs is a bad practice (yep, using them at all). 不同网站的一些人告诉大家,使用refs是一种不好的做法(是的,完全使用它们)。

What's the real deal with it? 什么是真正的处理? Is it something bad that I will attach it to, for example, child component (so I can access inner stuff)? 我将它附加到例如子组件(所以我可以访问内部的东西)是不是很糟糕?

Thanks! 谢谢!

React requires you to think the react way and refs are kind of a backdoor to the DOM that you almost never need to use. React要求你认为反应方式和refs是你几乎不需要使用的DOM的后门。 To simplify drastically, the react way of thinking is that once state changes, you re-render all the components of your UI that depend on that state. 为了大幅简化,反应思维方式是,一旦状态发生变化,您将重新呈现UI中依赖于该状态的所有组件。 React will take care of making sure only the right bits of the DOM are updated, making the whole thing efficient and hiding the DOM from you (kinda). React将负责确保只更新DOM的正确位,使整个事情变得高效并隐藏DOM(有点)。

For example, if your component hosts an HTMLInputElement, in React you'll wire up an event handler to track changes to the input element. 例如,如果组件承载HTMLInputElement,则在React中,您将连接一个事件处理程序以跟踪对input元素的更改。 Whenever the user types a character, the event handler will fire and in your handler you'll update your state with the new value of the input element. 每当用户键入一个字符时,事件处理程序将触发,并且在处理程序中,您将使用input元素的新值更新状态。 The change to the state triggers the hosting component to re-render itself, including the input element with the new value. 对状态的更改会触发托管组件重新呈现自身,包括具有新值的input元素。

Here's what I mean 这就是我的意思

 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> 

Notice how anytime the input value changes, the handler gets called, setState gets called and the componet will re-render itself in full. 注意输入值改变的任何时候,处理程序被调用,setState被调用,组件将完全重新呈现。

Its generally bad practice to think about refs because you might get tempted to just use refs and and do things say the JQuery way, which is not the intention of the React architecture/mindset. 考虑引用通常是不好的做法因为你可能只想使用引用并且做事情就像JQuery那样,这不是React架构/思维模式的意图。

The best way to really understand it better is to build more React apps & components. 更好地理解它的最好方法是构建更多React应用程序和组件。

Hmm... Not sure it qualifies as an answer, but it became too long-form for a comment. 嗯...不确定它是否有资格作为答案,但它的评论太长了。

Imagine you have a Dashboard that contains widgets showing various states of a system. 想象一下,您有一个仪表板,其中包含显示系统各种状态的小部件。 Each widget has its own data source and its own controls. 每个小部件都有自己的数据源和自己的控件。 Perhaps they are even refreshed from time to time. 也许他们甚至不时地精神焕发。 However, when user wants to see an updated view of the system there is a "Refresh" button at Dashboard level. 但是,当用户想要查看系统的更新视图时,在仪表板级别有一个“刷新”按钮。 Implementing such a button is not trivial. 实现这样一个按钮并非易事。

If you are in a Redux application - you'd have a choice - "faking" dispatch('refresh') for all the children. 如果您使用的是Redux应用程序 - 您可以选择 - 为所有孩子进行“伪造” dispatch('refresh') To decouple it, each widget, upon loading registers an action, so that parent simply goes through all actions and fires them, when imperative refresh is needed. 为了解耦它,每个小部件在加载时注册一个动作,这样当需要进行必要的刷新时,父级只需完成所有操作并触发它们。

In a non Redux/Flux system, or in more complex/dynamic scenarios, this may not be possible or may not be as straightforward. 在非Redux / Flux系统中,或在更复杂/动态的场景中,这可能是不可能的,也可能不是那么简单。 It then may be better, complexity wise, to expose refresh method on all widgets and then access it from the parent (or, rather, owner): 然后,在所有小部件上公开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>
        );
    }
}

Something like that, with less verbosity, of course. 当然,有类似的东西,不那么冗长。

As side note, I upvoted @skav answer and think that these scenarios should be avoided. 作为旁注,我赞成@skav回答并认为应该避免这些情况。 This is an exception. 这是一个例外。

CodePen Example CodePen示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM