在React中使用refs的不良做法是什么?

时间:2016-11-12 22:27:38

标签: javascript reactjs refs

我开始学习React。不同网站的一些人告诉大家使用refs是一种不好的做法(是的,完全使用它们)。

真正的处理方式是什么?我将它附加到例如子组件(所以我可以访问内部组件)这是不是很糟糕吗?

谢谢!

2 个答案:

答案 0 :(得分:14)

React要求你think the react way和refs是你几乎不需要使用的DOM的后门。为了大幅简化,反应思维方式是,一旦状态发生变化,您将重新呈现依赖于该状态的UI的全部组件。 React将确保只更新DOM的正确位,使整个事物变得高效并隐藏DOM(有点)。

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

这就是我的意思

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被调用,而componet将完全重新呈现。

考虑refs通常是不好的做法,因为你可能只想使用refs并且做一些事情就说JQuery方式,这不是React架构/思维模式的意图。

更好地理解它的最好方法是构建更多React应用程序&amp;组件。

答案 1 :(得分:2)

嗯...不确定它是否有资格作为答案,但是评论的篇幅太长了。

想象一下,你有一个仪表板,其中包含显示系统各种状态的小部件。每个小部件都有自己的数据源和自己的控件。也许他们甚至不时地精神焕发。但是,当用户想要查看系统的更新视图时,有一个&#34;刷新&#34;仪表板级别的按钮。实现这样一个按钮并非易事。

如果您使用的是Redux应用程序 - 您可以选择 - &#34;伪装&#34;所有孩子都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回答并认为这些场景   应该避免。这是一个例外。

CodePen Example