M
M
Max Zhukov2019-03-21 10:35:37
React
Max Zhukov, 2019-03-21 10:35:37

Why does it enter the render function through react-hooks?

Hello everyone, this is a snippet of a custom hook, can you tell me why it doesn’t enter the renderSourceList (as it should if the sources have not changed), but it always enters the renderItem (although I use useMemo here too)?

const renderItem = useMemo(() => (source) => {
        const { name: sourceName } = source;
        const labelClassName = `source__label-name source__label-name-${sourceName.toLowerCase()}`;
        return (
            <List.Item className="source">
                <Checkbox
                    disabled={source.name === 'radius'}
                    checked={source.isSelected}
                    onChange={() => handleSourceChecked(source)}
                    className="source__checkbox"
                />
                <span className={classNames('source__label', labelClassName)}>
                    {dataSourceLabelConfig[sourceName] || sourceName.toUpperCase() }
                </span>
                <span className="source__label">{`${source.nodeCount} nodes`}</span>
                <span className="source__label source__label-date">
                    {fromNow(source.updated)}
                </span>
                <button className="source__button" type="button" onClick={() => handleSourceRefresh(source)}>
                    <Icon className="source__icon" type="reload" width="20" height="20" />
                </button>
            </List.Item>
        );
    }, [sources]);


    const renderSourceList = useMemo(() => () => {
        const newSources = [...sources];
        if (newSources.length) {
            newSources.push({
                name: 'radius',
                isSelected: false,
                updated: newSources[0].updated,
                nodeCount: 0
            });
        }
        return (
            <Card title="Sources">
                <List
                    size="small"
                    dataSource={newSources}
                    renderItem={renderItem}
                    split={false}
                />
            </Card>
        );
    }, [sources]);

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Spirin, 2019-03-21
@rockon404

Are you sure you understand how the useMemo call works? In your case, it returns a render function that is called every time and is recalculated only if the sources property has changed. Moreover, the sources property is not even used in renderItem, so you should not notice anything.
In the form in which you use useMemo, it makes no sense to use it. It's more appropriate to just take out these functions as separate components. Or take out only renderItem, and rewrite renderSourceList like this:

renderSourceList = useMemo(() => {
  if (newSources.length) {
    // ...
  }
  return (
    // ...
  );
});

Then you will get a memorized value. But this is only relevant if the component is frequently redrawn and the list does not change.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question