Files
react-native/packages/rn-tester/js/examples/Performance/performanceComparisonExamples/EffectInRenderExample.js
T
Moti Zilberman d6e0bc714a Enable lint/sort-imports everywhere (#41334)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41334

TSIA.

Changelog: [Internal]

Reviewed By: robhogan

Differential Revision: D51025812

fbshipit-source-id: e10d437be775a6b80946483aa96460f34927f870
2023-11-06 12:59:38 -08:00

132 lines
3.7 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
'use strict';
import type {ItemDataType} from '../components/itemData';
import {generateRandomItems} from '../components/itemData';
import ItemList from '../components/ItemList';
import * as React from 'react';
import {StrictMode, useCallback, useEffect, useState} from 'react';
import {Text} from 'react-native';
const TIMEOUT = 500;
const FETCH_COUNT = 250;
const ItemListMemo = React.memo(ItemList);
function ItemFetcherBadExample(props: {
onFetched: (items: ItemDataType[]) => void,
count: number,
}): React.Node {
const {onFetched, count} = props;
const fetchMoreItems = async (
itemsCount: number,
): Promise<ItemDataType[]> => {
return new Promise(resolve => {
setTimeout(() => {
resolve(generateRandomItems(itemsCount));
}, TIMEOUT);
});
};
fetchMoreItems(count).then((items: ItemDataType[]) => {
onFetched(items);
}, console.error);
}
function ItemFetcherGoodExample(props: {
onFetched: (items: ItemDataType[]) => void,
count: number,
}): React.Node {
const {onFetched, count} = props;
useEffect(() => {
const fetchMoreItems = async (
itemsCount: number,
): Promise<ItemDataType[]> => {
return new Promise(resolve => {
setTimeout(() => {
resolve(generateRandomItems(itemsCount));
}, TIMEOUT);
});
};
fetchMoreItems(count).then((items: ItemDataType[]) => {
onFetched(items);
}, console.error);
}, [onFetched, count]);
}
const ItemFetcherBadExampleMemo = React.memo(ItemFetcherBadExample);
const ItemFetcherGoodExampleMemo = React.memo(ItemFetcherGoodExample);
function EffectInRenderBadExample(): React.Node {
const [visibleItems, setVisibleItems] = useState<ItemDataType[]>([]);
const [fetchedItems, setFetchedItems] = useState<ItemDataType[]>([]);
const onMoreItemFetched = useCallback(
(items: ItemDataType[]) => {
setFetchedItems(items);
},
[setFetchedItems],
);
if (fetchedItems.length > 0) {
setVisibleItems(visibleItems.concat(fetchedItems));
setFetchedItems([]);
}
return (
<StrictMode>
<Text>{`Items count in list: ${visibleItems.length}`}</Text>
<ItemFetcherBadExampleMemo
onFetched={onMoreItemFetched}
count={FETCH_COUNT}
/>
<ItemListMemo data={visibleItems} />
</StrictMode>
);
}
function EffectInRenderGoodExample(): React.Node {
const [visibleItems, setVisibleItems] = useState<ItemDataType[]>([]);
const [fetchedItems, setFetchedItems] = useState<ItemDataType[]>([]);
const onMoreItemFetched = useCallback(
(items: ItemDataType[]) => {
setFetchedItems(items);
},
[setFetchedItems],
);
if (fetchedItems.length > 0) {
setVisibleItems(visibleItems.concat(fetchedItems));
setFetchedItems([]);
}
return (
<StrictMode>
<Text>{`Items count in list: ${visibleItems.length}`}</Text>
<ItemFetcherGoodExampleMemo
onFetched={onMoreItemFetched}
count={FETCH_COUNT}
/>
<ItemListMemo data={visibleItems} />
</StrictMode>
);
}
export default {
title:
'Directly trigger side effect in render may run multiple times and cause error state or re-renders',
description:
'Trigger a side effect in render method without using effect hook in <StrictMode>. This will force render component two times, and the side effect in bad example caused append items to the list two times unexpectedly.',
Bad: EffectInRenderBadExample,
Good: EffectInRenderGoodExample,
};