react-cached-callback
react-cached-callback
là một trợ giúp để loại bỏ các hàm mũi tên và bind trong các chu trình của phương thức render
của thành phần react
.
Gói này chứa các trợ giúp sau:
- trang trí cached (makeCached)
- sử dụng useGetCallback
- sử dụng useEventCallback
- sử dụng useGetEventCallback
Ví dụ với cached
:
import cached from 'react-cached-callback';
class SomeComponent extends React.Component {
@cached
_onClick(index) {
return () => doSomething(index);
}
render() {
return (
<div>
{someArray.map((obj, index) => (
<ChildComponent onClick={this._onClick(index)} />
))}
</div>
);
}
}
Ví dụ với useGetCallback
:
import { useGetCallback } from 'react-cached-callback';
function SomeComponent ({someProp}) {
const getOnClick = useGetCallback(
(index) => () => {
doSomething(index, someProp);
},
[someProp]
);
return (
<div>
{someArray.map((obj, index) => (
<ChildComponent onClick={getOnClick(index)} />
))}
</div>
);
}
Tại sao?
Không được khuyến nghị tạo ra các hàm mới trong mỗi cuộc gọi hàm render
trong react
và truyền chúng cho các thành phần con. Điều đó là do lý do tối ưu hóa hiệu suất. Hiệu suất có thể giảm khi bạn sử dụng hàm mũi tên hoặc bind trong hàm render
. Thông thường, bạn có thể dễ dàng tránh điều này bằng cách tạo một thuộc tính của thành phần với một hàm mũi tên:
class SomeComponent extends React.Component {
_onClickHandler = () => {
...
}
render() {
return (
<div >
<ChildComponent onClick={this._onClickHandler} />
</div>
);
}
}
Nhưng đôi khi bạn cần truyền onClickHandler
cho một số thành phần trong chu kỳ. Và onClickHandler
cần biết chỉ số của phần tử khi nó được thực thi. react-cached-callback
sẽ giúp bạn giải quyết vấn đề này một cách dễ dàng.
@cached
Cách nó hoạt động
Để sử dụng cached
, bạn cần thêm vào một thành phần một phương thức tạo các callback cho mỗi thành phần được hiển thị trong chu kỳ. Sau đó, bạn cần trang trí nó bằng cached
. Ví dụ:
@cached
_createOnClick(index) {
return () => doSomething(index);
}
render() {
return (
<div>
{someArray.map((obj, index) => (
<ChildComponent onClick={this._createOnClick(index)} />
))}
</div>
);
}
Khi _createOnClick
được gọi lần đầu với một chỉ số nào đó, cached
lưu trữ một callback được trả về bởi _createOnClick
gốc, tạo một bọc cho nó và trả về bọc đó.
Khi _createOnClick
được gọi với cùng một chỉ số lần tiếp theo, cached
nhận một callback mới từ _createOnClick
gốc, lưu trữ nó và trả lại bọc đã được tạo trước đó. Khi bọc được gọi, nó gọi một callback đã được trả về bởi _createOnClick
gốc lần cuối cùng.
Để xác định wrapper nào sẽ được trả về, cached
sử dụng một key. Trong ví dụ ở trên, tham số đầu tiên (index
) được sử dụng làm key. Bạn có thể chỉ định một key khác. Xem phần Tham số để biết thêm chi tiết.
Tham số
Trang trí cached
có thể được sử dụng với một tham số hoặc không có tham số. Tham số này có thể là một đối tượng, một số hoặc một hàm.
// with object with parameters
@cached({index: 1, pure: false})
// with number
@cached(1)
// with function
@cached((obj) => obj.id)
// without parameters
@cached
//or
@cached()
Bạn có thể truyền các tham số sau cho cached
:
- index (number) – chỉ số của một tham số sẽ được sử dụng làm key
- getKey (function) – hàm tính toán key. Nó không thể được sử dụng cùng với index.
- pure (boolean) – nếu pure là true,
cached
sẽ không gọi phương thức gốc để lấy một callback nếu nó được gọi với các tham số giống nhau lần sau.
không có tham số
Nếu cached
được sử dụng mà không có tham số, tham số đầu tiên sẽ được sử dụng làm key:
@cached
_onClick(index) {
return () => doSomething(index);
}
render() {
return (
<div>
{someArray.map((obj, index) => (
<ChildComponent onClick={this._onClick(index)} />
))}
</div>
);
}
index
được sử dụng làm key ở đây. Nếu _onClick
được gọi với cùng một index lần sau, cùng một wrapper sẽ được trả về.
index
Bạn có thể sử dụng bất kỳ tham số nào làm key bằng cách chỉ định chỉ số của tham số.
@cached({index: 1})
// or
@cached(1)
_onClick(obj, index) {
return () => doSomething(obj);
}
render() {
return (
<div>
{someArray.map((obj, index) => (
<ChildComponent onClick={this._onClick(obj, index)} />
))}
</div>
);
}
getKey
Bạn có thể chỉ định một hàm để tính toán key bằng cách sử dụng các tham số đã truyền:
@cached((obj) => obj.id)
// or
@cached({getKey: (obj) => obj.id})
_onClick(obj) {
return () => doSomething(obj);
}
render() {
return (
<div>
{someArray.map((obj) => (
<ChildComponent onClick={this._onClick(obj)} />
))}
</div>
);
}
getKey
nhận các tham số giống như phương thức gốc. Trong trường hợp này, getKey
sẽ nhận một tham số – obj
, và id của obj sẽ được sử dụng làm key.
Nếu getKey
được truyền cho @cached
, thì tham số index
sẽ bị bỏ qua.
pure
Khi một bọc đối tượng được gọi với tất cả các tham số giống nhau trong lần gọi tiếp theo, nó sẽ không gọi hàm _onClick
gốc và sử dụng kết quả đã được lưu trữ. Nếu ít nhất một tham số thay đổi, hàm _onClick
gốc sẽ được gọi. Nếu bạn cần gọi hàm _onClick
gốc mỗi lần, bạn có thể chỉ định tham số pure
thành false
:
@cached({pure: false})
_onClick(obj) {
return () => doSomething(obj);
}
makeCached
Nếu bạn không thể sử dụng trình trang trí, bạn có thể sử dụng hàm trợ giúp makeCached
. Nó có giao diện như sau:
makeCached(component: object, methodName: string, params?: object)
- component – lớp thành phần react (hoặc một lớp khác)
- methodName – tên của phương thức mà bạn muốn lưu trữ kết quả
- params – các tham số giống nhau như trang trí
cached
nhận
không có tham số
import { makeCached } from 'react-cached-callback';
class SomeComponent extends React.Component {
_onClick(index) {
return () => doSomething(index);
}
render() {
return (
<div>
{someArray.map((obj, index) => (
<ChildComponent onClick={this._onClick(index)} />
))}
</div>
);
}
}
makeCached(SomeComponent, '_onClick');
chỉ mục
makeCached(SomeComponent, '_onClick', {index: 1});
// or
makeCached(SomeComponent, '_onClick', 1);
getKey
makeCached(SomeComponent, '_onClick', {getKey: (obj) => obj.id});
// or
makeCached(SomeComponent, '_onClick', (obj) => obj.id);
pure
makeCached(SomeComponent, '_onClick', {pure: false);
useGetCallback
Hook useGetCallback
tương tự như hook useCallback
của react, nhưng useGetCallback
giúp tạo ra nhiều hàm gọi lại trong chu kỳ.
import { useGetCallback } from 'react-cached-callback';
function SomeComponent ({someProp}) {
const getOnClick = useGetCallback(
(obj) => () => {
doSomething(obj, someProp);
},
(obj) => obj.id,
[someProp]
);
return (
<div>
{someArray.map((obj) => (
<ChildComponent onClick={getOnClick(obj)} />
))}
</div>
);
}
Sau mỗi lần render, useGetCallback
lưu trữ các hàm gọi lại được tạo ra và trả về chúng trong lần render tiếp theo. Để xác định hàm gọi lại nào sẽ được trả về, useGetCallback
sử dụng một key. Theo mặc định, tham số đầu tiên được sử dụng làm key. Trong ví dụ trên, id của một đối tượng được sử dụng làm key.
Bạn có thể truyền các tham số sau cho useGetCallback
:
- getCallback (hàm) – hàm này nên trả về một hàm gọi lại.
- keyIndex (số) hoặc getKey (hàm) tùy chọn – chỉ mục của một tham số mà bạn muốn sử dụng làm key hoặc một hàm mà bạn muốn trả về một key. Hàm
getKey
nhận tất cả các tham số giống nhau như hàm tạo ra các hàm gọi lại. - dependencies (mảng) tùy chọn – các giá trị được sử dụng trong hàm gọi lại. Tương tự như các phụ thuộc của
useCallback
trong React.
useGetCallback
trả về một hàm gọi lại mới cho một khóa nào đó mỗi khi một trong số các phụ thuộc hoặc tham số gọi (callParams
trong ví dụ bên dưới) thay đổi.
const getCallback = useGetCallback(
(...callParams) => {
return () => doSomething(...callParams)
},
dependencies
);
useEventCallback
Hook useEventCallback
có thể được sử dụng như useCallback
trong React để tạo chỉ một hàm gọi lại. Tuy nhiên, khác với useCallback
, useEventCallback
không tạo ra một hàm gọi lại mới khi có sự thay đổi trong các phụ thuộc. Nó luôn trả về cùng một hàm.
useEventCallback
chỉ nhận một tham số duy nhất – một hàm gọi lại.
const callback = useEventCallback(
(callParams) => { doSomething(...callParams) }
);
useEventCallback
luôn trả về cùng một hàm, vì vậy quá trình render được tối ưu hóa hơn vì các thành phần con có thể render ít hơn. Tuy nhiên, điều này có thể là nguyên nhân gây ra lỗi ở chế độ bất đồng bộ. Vì vậy, bạn không nên sử dụng các hàm gọi lại như vậy sớm hơn khi quá trình render kết thúc. Bạn có thể sử dụng chúng trong các sự kiện giao diện người dùng như onClick
, onHover
và sau khi render – trong useEffect
. Sử dụng chúng trong useLayoutEffect
hoặc componentDidMount
/ componentDidUpdate
cũng có thể gây ra lỗi.
useGetEventCallback
useGetEventCallback
có thể được sử dụng để tạo nhiều hàm gọi lại trong các chu kỳ như useGetCallback
. Tuy nhiên, nó không tạo ra một hàm gọi lại mới khi có sự thay đổi trong các phụ thuộc hoặc tham số. Giống như useEventCallback
, bạn không nên sử dụng các hàm gọi lại được tạo bởi useGetEventCallback
trước khi quá trình render kết thúc.
Bạn có thể truyền các tham số sau vào useGetEventCallback
:
- getCallback (hàm) – hàm này nên trả về một hàm gọi lại.
-
keyIndex (số) hoặc getKey (hàm) tùy chọn – chỉ số của một tham số nào đó mà nên được sử dụng như một khóa hoặc một hàm nên trả về một khóa. Mặc định, tham số đầu tiên được sử dụng làm khóa. Hàm
getKey
nhận tất cả các tham số giống như hàm tạo ra các hàm gọi lại.const getOnClick = useGetEventCallback(
(obj) => {
return () => doSomething(obj)
},
(obj) => obj.id
);
Chi tiết tải về:
Tác giả: megazazik
Nguồn: https://github.com/megazazik/react-cached-callback
Giấy phép: MIT license