react refs_ref和Forward refs在React

react refs

React Refs are a useful feature that acts as a means to reference a DOM element.

React Refs是有用的功能,可作为引用DOM元素的手段。

But the question here is why can we not directly manipulate the DOM using normal JavaScript DOM Manipulation?

但是这里的问题是为什么我们不能使用普通JavaScript DOM操作直接操作DOM?

Here is an example of why normal JS DOM Manipulation won’t be as useful as Refs when it comes to using React.

这是为什么在使用React时,普通JS DOM操作不如Refs有用的示例。

Suppose you have a component which has multiple input element. Now, what if we want to focus on the second input element or any other input element as soon as we render the component?

假设您有一个包含多个输入元素的组件。 现在,如果我们要在渲染组件后立即专注于第二个输入元素或任何其他输入元素怎么办?

What happens when we use normal JS DOM Manipulation?

当我们使用普通的JS DOM操作时会发生什么?

import React, { Component } from 'react';export class InputRef extends Component {componentDidMount() {
document.querySelector('input').focus();
}render() {
return (
<div>
<input type="text" />
<input type="text" />
<input type="text" />
</div>
)
}}
export default InputRef;

Here we do indeed focus, but we always focus on the first input element. Simply because document.querySelector selects the first input element it finds in the entire DOM.This is because document.querySelector is not something that is related to React but is a general DOM Selector.

在这里,我们确实专注于,但我们始终专注于第一个输入元素。 仅仅是因为document.querySelector选择了它在整个DOM中找到的第一个输入元素,这是因为document.querySelector与React无关,而是一个通用的DOM选择器。

We can anyway add an id to these inputs and focus according to id, but React offers a better alternative. The Refs.

无论如何,我们可以向这些输入添加id并根据id进行关注,但是React提供了更好的选择。 裁判

Refs in Class-Based Components. Old Approach.

基于类的组件中的引用。 旧方法。

Here we pass a function (anonymous arrow function)in the input element which you want to focus on. The argument that we get is a reference to the element on which we place the function and we can use that reference in our function body.

在这里,我们在您要关注的输入元素中传递一个函数(匿名箭头函数)。 我们得到的参数是对放置函数的元素的引用,我们可以在函数主体中使用该引用。

import React, { Component } from 'react';export class InputRef extends Component {componentDidMount() {
this.inputElRef.focus();
}render() {
return (
<div>
<input type="text" />
<input type="text" ref={(inputElRef) => {this.inputElRef = inputElRef}}/>
<input type="text" />
</div>
)
}}
export default InputRef;`

Here this.inputElRef will store our reference in global property and hence we can access that reference anywhere in our component (in our case componetDidMount()).

在这里this.inputElRef将引用存储在全局属性中,因此我们可以在组件的任何位置(在本例中为componetDidMount())访问该引用。

Since React-16.3 we now have another way of using Ref and that uses CreateRef.

从React-16.3开始,我们现在有了使用Ref和CreateRef的另一种方法。

Here instead of passing a function to Ref, we can directly assign the value that we have using createRef to our input element.

在这里,除了将函数传递给Ref之外,我们还可以使用createRef将我们拥有的值直接分配给输入元素。

import React, { Component } from 'react';export class InputRef extends Component {constructor(props) {
super(props);
this.inputElRef = React.createRef();
}componentDidMount() {
this.inputElRef.current.focus();
}render() {
return (
<div>
<input type="text" />
<input type="text" ref={inputElRef}/>
<input type="text" />
</div>
)
}}
export default InputRef;`

Just a side note here. We will have to access the ref using the current property which gives us access to current reference.

这里只是一个旁注。 我们将不得不使用current属性访问ref 这使我们可以访问当前参考。

Refs with react hooks

带反钩的裁判

To use Refs in React hooks we have a hook provided by React — useRef.

要在React钩子中使用Refs,我们有一个由React提供的钩子-useRef。

import React , { useEffect ,  useRef } from 'react'const inputRef = (props) => { const inputElRef = useRef(null);
useEffect(() => {
inputElRef.current.focus();
}, []) return (
<div>
<input type="text" />
<input type="text" ref={inputElRef}/>
<input type="text" />
</div>
)
}
export default inputRef;

Side Note: We can pass an initial value in useRef to store any value, hence useRef is not just used to get access for the DOM element but we can store any other values as well. For this example, however, we pass null as an initial value.

旁注:我们可以在useRef中传递初始值以存储任何值,因此useRef不仅用于获取DOM元素的访问权限,而且还可以存储任何其他值。 但是,对于此示例,我们将null用作初始值。

现在,我们知道了如何创建引用,我们可以讨论如何转发引用。 (Now as we know how to create a ref we can talk about how to Forward a Ref.)

Forwarding ref is a technique for automatically passing a ref through a component to one of its child components.

转发参考是一种自动将参考通过组件传递到其子组件之一的技术。

I’ll try to explain what forward Ref does through a basic use case.

我将通过一个基本用例来解释Ref的作用。

Suppose we have a Navbar component and we have a Home Component. Our Home Component has two sections viz “Our Services”, “Contact-Us”.Navbar Component will have links to these Sections which when clicked will scroll us to that particular Section.

假设我们有一个Navbar组件,而我们有一个Home组件。 我们的主页组件有两个部分,即“我们的服务”,“联系我们”。导航栏组件将具有指向这些部分的链接,单击这些链接可将我们滚动到该特定部分。

Now an easy and direct way for this is to pass the id of a section in href directly.

现在,一种简单直接的方法是直接在href中传递节的ID。

<a href={"#serviceId"} >Our Services</a>

<a href={"#serviceId"} >Our Services</a>

But to give you an example on how Forward ref work let’s pass on the id from Home Component to NavBar Component via our Parent Component. Looks a bit convoluting but it is damn easy!! :)

但是,为您提供有关Forward ref工作方式的示例,让我们通过父组件将ID从Home组件传递到NavBar组件。 看起来有点令人费解,但是这太简单了!! :)

Now the typical React Structure will look something like this.We will have a parent Layout/App Component which will have a component of Navbar and Home. (i.e Home and NavBar are children to Layout Component)

现在典型的React Structure看起来像这样。我们将有一个父级Layout / App Component,它将有Navbar和Home的组件。 (即Home和NavBar是布局组件的子代)

Now, this is how we will forward Refs:

现在,这就是我们将转发引用的方式:

Step 1: Create a ref for the Home Section in Parent Component (Layout). Pass all the refs as a single object.

步骤1:在“父组件(布局)”中为“主页”部分创建引用。 将所有ref作为单个对象传递。

import React, { Component } from 'react';
import './App.css';
import NavBar from './components/NavBar/NavBar';
import Home from './components/Home/Home';class App extends Component {constructor(props) {
super(props);
this.homeRefService = React.createRef();
this.homeRefContact = React.createRef();
}render() {
return (
<div className="App">
<NavBar />
<Home ref={{homeRefService: this.homeRefService, homeRefContact: this.homeRefContact }}/>
</div>
);
}

}export default App;

Step 2: Forward this ref in Home Component using the dot forwardRef method from React Library.

步骤2:使用React Library中的dot forwardRef方法在Home Component中转发此ref。

The forward Ref method takes a component as its parameter. So we will have to pass the functional Home component as a parameter to forwardRef. Now every component receives “props ” as its parameter, but when we use forwardRef method, we can pass “ref” as a second parameter for that component.
It will be clear when we see the below code for Home Component.

forward Ref方法将组件作为其参数 因此,我们将必须将功能性Home组件作为参数传递给forwardRef。 现在,每个组件都将“ props”作为其参数,但是当使用forwardRef方法时,可以将“ ref”作为该组件的第二个参数。 当我们看到下面的Home Component代码时,将很清楚。

import React from 'react';const home = React.forwardRef((props , ref) => {
console.log('Ref', ref);
return (
<div>
<section>
Our Services
</section> <section>
Contact Us
</section>
</div>
)
})export default home

The output of console.log right now will be :

现在console.log的输出将是:

{homeRefContact: {current: null}
homeRefService: {current: null}}

We can then use Object Destructuring to get the refs for each section respectively and we pass the corresponding refs to each section.

然后,我们可以使用对象解构分别获取每个部分的引用,然后将相应的引用传递给每个部分。

const { homeRefService , homeRefContact } = ref;<section ref={homeRefService} id="Services"> Our Services </section>
<section ref={homeRefContact}id="Contact"> Contact Us </section>

Once we pass these refs in each section on our Home Component, we will now have reference to these in our Parent Component (App / Layout).

一旦在Home组件的每个部分中传递了这些引用,我们现在将在Parent Component(应用程序/布局)中引用这些引用。

Step 3: Since now we have the reference of sections present in the Home Component in our App Component (because of forward ref) we set the ref in state of App Component and then pass these refs as props to the NavBar component. Below is the code for App.js.

步骤3 :由于现在我们已经引用了App组件中Home组件中存在的部分(由于前向引用),我们将ref设置为App Component状态,然后将这些引用作为prop传递给NavBar组件。 以下是App.js的代码。

constructor(props) {
super(props);
this.homeRefService = React.createRef();
this.homeRefContact = React.createRef();
this.state = { homeServiceId: "", homeContactId: "" }
}componentDidMount() {
this.setState({
homeServiceId: this.homeRefService.current.id,
homeContactId: this.homeRefContact.current.id
});
}render() {
return (
<div className="App">
<NavBar homeServiceId={this.state.homeServiceId} homeContactId={this.state.homeContactId}/>
<Home ref={{homeRefService: this.homeRefService, homeRefContact: this.homeRefContact }}/>
</div>
);
}

A side note here:

这里的边注:

The ref is only accessible when the component gets mounted to the DOM. So we will have to access the DOM element in componentDidMount and hence we need to maintain a state in App.js for these refs.

仅当组件安装到DOM时,才能访问引用 因此,我们将必须访问componentDidMount的DOM元素,因此我们需要在App.js中维护这些引用的状态。

Step 4: Finally we want to access the props in our NavBar component to get the id for these refs.

步骤4:最后,我们要访问NavBar组件中的props以获取这些引用的ID。

export class NavBar extends Component {
render() {
return (
<div>
<a href={'#' + this.props.homeServiceId}> Our Services</a>
<a href={'#' + this.props.homeContactId}>Contact Us</a>
</div>
)
}
}

If you need to implement this functionality, you can add a CSS property ofscroll-behavior: smooth; and provide height to each section to check the scroll behavior.

如果您需要实现此功能,则可以添加以下CSS属性scroll-behavior: smooth; 并为每个部分提供高度以检查滚动行为。

结论 (Conclusion)

We had a basic understanding of how ref actually works and how can we use forward ref. Using refs will definitely make our React code better as we will be more decisive in how we manage our state, props, and re-rendering. To read more about refs check out the docs here.

我们对ref的实际工作方式以及如何使用前向ref有基本的了解。 使用ref绝对可以使我们的React代码更好,因为我们将更加决定性地管理状态,道具和重新渲染。 要了解有关裁判的更多信息,请在此处查看文档。

翻译自: https://medium.com/swlh/refs-and-forward-refs-in-react-be5bcb86fc69

react refs

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值