diff --git a/content/docs/refs-and-the-dom.md b/content/docs/refs-and-the-dom.md index 8802d0c7d..21d04ae20 100644 --- a/content/docs/refs-and-the-dom.md +++ b/content/docs/refs-and-the-dom.md @@ -10,34 +10,33 @@ redirect_from: - "tips/expose-component-functions.html" - "tips/children-undefined.html" --- +Refs là một cách giúp chúng ta truy cập đến những nút DOM hoặc những phần tử React được tạo ra trong phương thức render. -Refs cung cấp một cách để truy cập DOM nodes hoặc các React elements được tạo trong phương thức render. - -Trong luồng dữ liệu đặc trưng của React, [props](/docs/components-and-props.html) là cách duy nhất để các parent components tương tác với child của chúng. Để thay đổi child, bạn re-render nó với props mới. Tuy nhiên, có một vài trường hợp mà ở đó bạn cần thay đổi child bên ngoài luồng dữ liệu đặc trưng ở thức mệnh lệnh. Child được thay đổi có thể là một thể hiện của một React component, hoặc nó có thể là DOM element. Đối với cả hai trường hợp này, React cung cấp một cách để giải quyết. +Trong luồng dữ liệu của React, [props](/docs/components-and-props.html) là cách duy nhất để các component cha tương tác với component con. Để cập nhật component con, ta phải re-render nó với các props mới. Tuy nhiên, một số trường hợp buộc ta phải thay đổi thành phần con bên ngoài luồng dữ liệu điển hình của React. Component con được sửa đổi có thể là một instance của một React component, hoặc nó có thể là một DOM element. Với những trường hợp trên, ta có thể xử lý bằng Refs. ### Khi nào sử dụng Refs {#when-to-use-refs} -Có vài trường hợp tốt để sử dụng refs: +Một vài trường hợp hữu ích để sử dụng refs: * Quản lý focus, text selection, hoặc media playback. -* Kích hoạt animations quan trọng. -* Tích hợp với những thư viện DOM của bên thứ ba. +* Trigger animation của một element khác. +* Tích hợp những thư viện DOM từ bên thứ ba. -Tránh sử dụng refs cho bất cứ điều gì mà có thể được hoàn thành một cách khai báo. +Tránh sử dụng refs trong trường hợp chúng ta có thể khai báo. -Ví dụ, thay vì sử dụng các phương thức `open()` và `close()` cho một `Dialog` component, truyền một thuộc tính `isOpen` cho nó. +Ví dụ, thay vì hiển thị phương thức `open()` và `close()` trong `Dialog` component, thì chúng ta sẽ sử dụng `isOpen` như một prop để xử lý nó. -### Đừng lạm dụng Refs {#dont-overuse-refs} +### Không nên lạm dụng Refs {#dont-overuse-refs} -Xu hướng đầu tiên của bạn có thể là sử dụng ref để "làm cái gì đó hoạt động" trong ứng dụng của bạn. Nếu đúng như vậy, hãy dành một chút thời gian và suy nghĩ kỹ hơn về state nên được sử dụng ở đâu trong hệ thống phân cấp component. Thông thường, rõ ràng là nơi thích hợp để "đặt" state đó là ở một cấp cao hơn trong hệ thống phân cấp. Xem hướng dẫn [Lifting State Up](/docs/lifting-state-up.html) cho nhiều ví dụ về cách này. +Chúng ta hay có xu hướng sử dụng Refs để xử lý mọi thử xảy ra trong ứng dụng của mình. Nếu rơi vào trường hợp này, thì lời khuyên là bạn nên dành thời gian để suy nghĩ nhiều hơn về vị trí mà bạn nên đặt State trong hệ thống cập bậc component (Component Hierarchy) của bạn. Thông thường, để rõ ràng nhất, thì vị trí State sẽ được đặt ở cấp bậc cao nhất của Component Hierarchy. Bạn có thể tham khảo thêm hướng dẫn và các ví dụ tại đây [Lifting State Up](/docs/lifting-state-up.html). -> Chú ý +> Lưu ý > -> Các ví dụ phía dưới đã được cập nhật để sử dụng `React.createRef()` API được giới thiệu trong React 16.3. Nếu bạn đang sử dụng các phiên bản React trước, chúng tôi khuyến nghị bạn sử dụng [callback refs](#callback-refs) để thay thế. +> Những ví dụ bên dưới đã được cập nhật để sử dụng `React.createRef()` API được giới thiệu trong React 16.3. Nếu bạn sử dụng những phiên bản trước, React khuyên bạn nên sử dụng [callback refs](#callback-refs) để thay thế. ### Tạo Refs {#creating-refs} -Refs được tạo bằng `React.createRef()` và gán cho React elements thông qua thuộc tính `ref`. Refs thường được gán cho một instance property khi một component được xây dựng để chúng có thể được tham chiếu khắp component. +Refs được khởi tạo bằng `React.createRef()` và được gắn vào các React element thông qua thuộc tính `ref`. Refs thường được gán cho một element nào đó, tại đó chúng ta có thể tham chiếu đến tất cả các thành phần bên trong nó. ```javascript{4,7} class MyComponent extends React.Component { @@ -53,42 +52,42 @@ class MyComponent extends React.Component { ### Truy cập Refs {#accessing-refs} -Khi một ref được truyền cho một element trong `render`, một tham chiếu đến node có thể truy cập được bằng thuộc tính `current` của ref. +Khi một element có chứa ref `render`, chúng ta có thể sử dụng một thuộc tính của ref là `current` để truy cập đến node hiện tại. ```javascript const node = this.myRef.current; ``` -Giá trị của ref khác nhau phụ thuộc vào loại của node: +Giá trị tham chiếu khác nhau, phụ thuộc vào loại cuả node: -- khi thuộc tính `ref` được sử dụng trên một HTML element, `ref` tạo một constructor với `React.createRef()` nhận DOM element bên dưới là thuộc tính `current` của nó. -- Khi thuộc tính `ref` được sử dụng trên một custom class component, đối tượng `ref` nhận mounted instance của component là `current` của nó. -- **Bạn có thể không sử dụng thuộc tính `ref` cho function components** bởi vì chúng không có instances. +- Khi thuộc tính `ref` được sử dụng trong HTML element, `ref` sẽ nhận DOM element bên dưới làm thuộc tính `current` của nó. +- Khi thuộc tính `ref` được sử dụng trong class component tùy chỉnh, `ref` sẽ nhận instance của component làm thuộc tính `current` của nó. +- **Bạn không thể sử dụng thuộc tính `ref` trong function components** vì nó không có instances. -Các ví dụ dưới đây chứng minh sự khác biệt. +Các ví dụ dưới đây chứng minh sự khác biệt: -#### Thêm một Ref cho một DOM Element {#adding-a-ref-to-a-dom-element} +#### Thêm Ref vào một DOM Element {#adding-a-ref-to-a-dom-element} -Đoạn code này sử dụng một `ref` để lưu một tham chiếu đến một DOM node: +Đoạn code sử dụng `ref` để lưu trữ một tham chiếu đến một DOM node: ```javascript{5,12,22} class CustomTextInput extends React.Component { constructor(props) { super(props); - // create a ref to store the textInput DOM element + // Tạo ra một ref để lưu textInput DOM element this.textInput = React.createRef(); this.focusTextInput = this.focusTextInput.bind(this); } focusTextInput() { // Explicitly focus the text input using the raw DOM API - // Note: we're accessing "current" to get the DOM node + // Note: Chúng ra truy cập đến "current" để lấy DOM node this.textInput.current.focus(); } render() { - // tell React that we want to associate the ref - // with the `textInput` that we created in the constructor + // Nói với React chúng ta muốn liên kết tới ref + // Với `textInput` chúng ta đã tạo ở constructor return (
); @@ -161,13 +160,13 @@ class Parent extends React.Component { } ``` -Nếu bạn muốn cho phép mọi người lấy một `ref` cho function component của bạn, bạn có thể sử dụng [`forwardRef`](/docs/forwarding-refs.html) (có thể kết hợp với [`useImperativeHandle`](/docs/hooks-reference.html#useimperativehandle)), hoặc bạn có thể chuyển component sang class. +Nếu bạn muốn cho phép mọi người sử dụng `ref` từ function component của bạn, bạn có thể dùng [`forwardRef`](/docs/forwarding-refs.html) (có thể kết hợp với [`useImperativeHandle`](/docs/hooks-reference.html#useimperativehandle)), hoặc bạn có thể chuyển đổi component thành class. -Tuy nhiên, bạn có thể **sử dụng thuộc tính `ref` bên trong một function component** miễn là bạn tham chiếu đến một DOM element hoặc một class component: +Tuy nhiên, bạn có thể **sử dụng thuộc tính `ref` bên trong function component** miễn là bạn tham chiếu đến phần tử DOM hoặc class component: ```javascript{2,3,6,13} function CustomTextInput(props) { - // textInput must be declared here so the ref can refer to it + // textInput phải được khai báo ở đây để ref có thể tham chiếu đến nó const textInput = useRef(null); function handleClick() { @@ -189,25 +188,26 @@ function CustomTextInput(props) { } ``` -### Phơi bày DOM Refs cho Parent Components {#exposing-dom-refs-to-parent-components} +### Hiển thị DOM Refs cho Components cha {#exposing-dom-refs-to-parent-components} -Trong một số ít trường hợp, bạn có thể muốn truy cập vào một child's DOM node từ một parent component. Điều này thường không được khuyến nghị bởi vì nó phá vỡ tính đóng gói của component, nhưng đôi khi nó có thể hữu ích cho việc kích hoạt focus hoặc đo kích thước hoặc vị trí của một child DOM node. +Một số ít trường hợp, bạn muốn có quyền truy cập vào DOM node của element con từ component cha. Nhưng chúng tôi không khuyến khích điều đó vì nó sẽ phá hủy tính đóng gói của component, một số ít nó hữu dụng khi trigger focus hoặc xác định kích thước, vị trí của một DOM node con. -Mặc dù bạn có thể [thêm một ref cho child component](#adding-a-ref-to-a-class-component), đây không phải là một giải pháp lý tưởng, vì bạn sẽ chỉ nhận một component instance thay vì một DOM node. Ngoài ra, cách này sẽ không hoạt động với function components. +Mặc dù bạn có thể [thêm ref vào component con](#adding-a-ref-to-a-class-component), tuy nhiên đây cũng không phải là một ý tưởng tốt, vì cái bạn nhận được chỉ là một component instance chứ không phải là một DOM node. Ý tưởng này cũng sẽ không hoạt động với function components. -Nếu bạn sử dụng React 16.3 hoặc cao hơn, chúng tôi khuyến nghị sử dụng [ref forwarding](/docs/forwarding-refs.html) cho những trường hợp này. **Ref forwarding cho phép các components tham gia vào việc phơi bày bất kì child component's ref như là của chính chúng**. Bạn có thể tìm một ví dụ chi tiết về cách phơi bày một child's DOM node cho một parent component [trong tài liệu ref forwarding](/docs/forwarding-refs.html#forwarding-refs-to-dom-components). +Nếu bạn sử dụng React 16.3 hoặc các phiên bản mới hơn, chúng tôi gợi ý bạn sử dụng [ref forwarding](/docs/forwarding-refs.html) cho những trường hợp như thế này. **Ref forwarding cho phép các component tham gia hiển thị bất kỳ bản tham chiếu nào của component là con của nó**. Bạn có thể tìm hiểu chi tiết thông qua các ví dụ cách component cha hiển thị DOM node con của nó [tại ref forwarding documentation](/docs/forwarding-refs.html#forwarding-refs-to-dom-components). -Nếu bạn sử dụng React 16.2 hoặc thấp hơn, hoặc nếu bạn cần nhiều sự linh hoạt hơn mức được cung cấp bởi ref forwarding, bạn có thể sử dụng [cách tiếp cận thay thế này](https://gist.github.com/gaearon/1a018a023347fe1c2476073330cc5509) và truyền một cách rõ ràng một ref dưới dạng một prop tên khác. +Nếu bạn sử dụng React 16.2 hoặc các phiên bản thấp hơn, hoặc nếu bạn cần sự linh hoạt hơn được cung cấp bởi ref forwarding, bạn có thể sử dụng [cách tiếp cận thay thể này](https://gist.github.com/gaearon/1a018a023347fe1c2476073330cc5509) và chuyển một tham chiếu dưới dạng tên một prop khác. -Nếu có thể, chúng tôi khuyên bạn không nên để lộ các DOM nodes, nhưng nó có thể là một lối thoát hiểm hữu ích. Chú ý rằng phương pháp này yêu cầu bạn thêm một số code vào child component. Nếu bạn hoàn toàn không kiểm soát được triển khai của child component, lựa chọn cuối cùng của bạn là sử dụng [`findDOMNode()`](/docs/react-dom.html#finddomnode), nhưng nó không được khuyến khích và chấp nhận trong [`StrictMode`](/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage). +Khi có thể, chúng tôi khuyên bạn tránh để lộ các DOM node. Lưu ý rằng cách tiếp cận này yêu cầu bạn thêm một số đoạn code vào component con. Nếu bạn hoàn toàn không kiểm soát được việc triển khai thành phần con, lựa chọn cuối của bạn là sử dụng [`findDOMNode()`](/docs/react-dom.html#finddomnode), nhưng nó không được khuyến khích và không được chấp nhận trong [`StrictMode`](/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage). ### Callback Refs {#callback-refs} -React cũng hỗ trợ một cách khác để thiết lập các refs được gọi là "callback refs", cách này giúp kiểm soát chi tiết hơn khi refs được thiết lập và bị hủy bỏ. +React cũng hỗ trợ một cách set refs khác gọi là "callback refs", giúp kiểm soát tốt hơn khi set và unset ref. + +Thay vì chuyển thuộc tính `ref` được tạo từ `createRef()`, bạn chuyển nó thành một function. Function này sẽ nhận vào một React component instance hoặc HTML DOM element như một argument của nó, có thể được lưu trữ và truy cập ở một nơi khác. -Thay vì truyền vào một thuộc tính `ref` được tạo bởi `createRef()`, bạn truyền một function. Function này nhận React component instance hoặc HTML DOM element làm đối số của nó, được lưu trữ và truy cập ở nơi khác. +Ví dụ dưới đây thực hiện việc sử dụng một `ref` callback để lưu trữ tham chiếu tới một DOM node trong một thuộc tính instance. -Ví dụ dưới đây triển khai một mẫu phổ thông: sử dụng `ref` callback để lưu trữ một tham chiếu đến một DOM node trong một instance property. ```javascript{5,7-9,11-14,19,29,34} class CustomTextInput extends React.Component { @@ -251,9 +251,9 @@ class CustomTextInput extends React.Component { } ``` -React sẽ gọi `ref` callback với DOM element khi component mounts, và gọi nó với `null` khi component unmounts. Refs được đảm bảo được cập nhật trước `componentDidMount` hoặc `componentDidUpdate` kích hoạt. +React sẽ gọi `ref` callback với DOM element khi component mounts, và gọi `null` khi component unmounts. Refs đảm bảo được cập nhật trước khi `componentDidMount` hoặc `componentDidUpdate` khởi chạy. -Bạn có thể truyền callback refs giữa các components như bạn có thể với object refs được tạo bằng `React.createRef()`. +Bạn có thể chuyển callback refs giữa những component giống như các đối tượng tham chiếu được tạo bởi `React.createRef()`. ```javascript{4,13} function CustomTextInput(props) { @@ -275,16 +275,16 @@ class Parent extends React.Component { } ``` -Trong ví dụ trên, `Parent` truyền ref callback của nó như một thuộc tính `inputRef` cho `CustomTextInput`, và `CustomTextInput` truyền function này như một thuộc tính `ref` đặc biệt cho ``. Do đó, `this.inputElement` trong `Parent` sẽ được thiết lập cho DOM node tương ứng với `` element trong `CustomTextInput`. +Trong ví dụ trên, `Parent` sẽ chuyển ref callback dưới dạng một `inputRef` prop tới `CustomTextInput`, và `CustomTextInput` chuyển một function tương tự như một thuộc tính `ref` tới ``. Lúc đó `this.inputElement` ở `Parent` sẽ set DOM node tương ứng với `` element trong `CustomTextInput`. ### API lỗi thời: String Refs {#legacy-api-string-refs} -Nếu bạn đã làm việc với React trước đây, bạn có thể quen thuộc với một API cũ hơn trong đó thuộc tính `ref` là một string, như `"textInput"`, và DOM node được truy cập như `this.refs.textInput`. Chúng tôi khuyên bạn không nên làm như vậy bởi vì string refs có [một vài vấn đề](https://github.com/facebook/react/pull/8333#issuecomment-271648615), được cân nhắc là lỗi thời, và **có khả năng bị xóa trong một trong những bản phát hành trong tương lai**. +Nếu bạn đã làm việc với React trước đây, bạn có thể quen thuộc với một API cũ hơn trong đó thuộc tính `ref` là một String, như `"textInput"`, và DOM node được truy cập bằng `this.refs.textInput`. Chúng tôi khuyên bạn nên tránh sử dụng nó vì string refs có [một vài vấn đề](https://github.com/facebook/react/pull/8333#issuecomment-271648615), liên quan đến kế thừa, và **có khả năng bị xóa trong các bản phát hành tiếp theo.**. -> Chú ý +> Lưu ý > -> Nếu bạn hiện đang sử dụng `this.refs.textInput` để truy cập refs, chúng tôi khuyến nghị bạn sử dụng [mẫu callback](#callback-refs) hoặc [`createRef` API](#creating-refs) để thay thế. +> Nếu hiên tại bạn đang sử dụng `this.refs.textInput` để truy cập đến refs, chúng tôi khuyên bạn nên sử dụng [callback pattern](#callback-refs) hoặc [`createRef` API](#creating-refs) để thay thế. ### Cảnh báo với callback refs {#caveats-with-callback-refs} -Nếu `ref` callback được định nghĩa như một inline function, nó sẽ được gọi hai lần trong quá trình cập nhật, lần đầu với `null` và lần sau với DOM element. Điều này là bởi vì một instance mới của function được tạo lại với mỗi lần render, vì vậy React cần xóa ref cũ và thiết lập ref mới. Bạn có thể tránh điều này bằng cách định nghĩa `ref` callback như là một thuộc tính trong class, nhưng lưu ý rằng nó không quan trọng trong hầu hết các trường hợp. +Nếu `ref` callback được định nghĩa như một inline function, nó sẽ được gọi 2 lần khi cập nhật, lần thứ 1 có giá trị là `null` và lần thứ 2 là DOM element. Điều này xảy ra bởi vì một instance của function được tạo ra sau mỗi lần render, React cần phải xóa những ref cũ và set up một cái mới. Bạn có thể tránh điều này bằng cách định nghĩa `ref` callback như một method trên class, nhưng nó cũng không quan trọng trong hầu hết các trường hợp.