Я хочу знать, является ли это антипаттерном или каким-то образом влияет на компонент, чтобы сделать что-то вроде этого:
render() {
const MyFuncComponent = ({ prop1, prop2 }) => (
// code here
)
return (
<div>
<MyFuncComponent prop1 = {something} prop2 = {else} />
</div>
)
}
Я не думаю, что мы должны это делать. Таким образом, каждый раз, когда состояние обновляется, функция переопределяется.
@ArpitKapadia да, в этом есть смысл, спасибо!
… И я уверен, что React не заметит, что это все тот же компонент.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я думаю, что в целом люди избегают определения функций в рендере, но, согласно это сообщение в блоге, это не обязательно плохая практика. Сообщение в блоге фокусируется на функциях встроенных обработчиков событий, определяемых в рендере, но я предполагаю, что это применимо к любой функции, определенной в рендере. Определение функций в рендере означает накладные расходы на их переопределение каждый раз при вызове рендеринга, но это может не иметь заметной разницы в производительности в зависимости от вашего компонента.
Для конкретного примера, который вы привели, я бы рекомендовал не определять другой компонент реакции в рендере. Если вы все же определяете какие-либо функции в рендере, они должны быть связаны с тем, что делает рендер. Определение другого компонента или добавление кучи функций внутри рендера может сделать его громоздким и трудным для понимания того, что делает код.
Да, это антипаттерн по той же причине, что мы не должны использовать компонент высшего порядка внутри render.
Don’t Use HOCs Inside the render Method
React’s diffing algorithm (called reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from
renderis identical (===) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they’re not equal, the previous subtree is unmounted completely.Normally, you shouldn’t need to think about this. But it matters for HOCs because it means you can’t apply a HOC to a component within the render method of a component:
render() { // A new version of EnhancedComponent is created on every render // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); // That causes the entire subtree to unmount/remount each time! return <EnhancedComponent />; }The problem here isn’t just about performance — remounting a component causes the state of that component and all of its children to be lost.
Это означает, что новый компонент появится в дереве React (которое можно изучить с помощью реагировать-devtools), но он не сохранит никакого состояния, а методы жизненного цикла, такие как componentDidMount, componentWillUnmount, useEffect, всегда будут вызываться в каждом цикле рендеринга.
Поскольку, вероятно, есть причины для динамического создания компонента, вот несколько общих шаблонов, позволяющих избежать ловушек.
Либо в собственном файле, либо непосредственно над определением родительского компонента. Передайте любую переменную в качестве свойств вместо использования родительской области компонента для доступа к значениям.
const MyFuncComponent = ({ prop1, prop2 }) => <>{/* code here */}</>;
const MyComponent = props => (
<div>
{props.list.map(({ something, thing }) => (
<MyFuncComponent prop1 = {something} prop2 = {thing} />
))}
</div>
);
Обычная функция, возвращающая JSX, может быть определенный и использовал непосредственно внутри другого компонента. Он не будет отображаться как новый компонент в дереве React, будет отображаться только его результат, как если бы он был встроен.
Таким образом, мы также можем использовать переменные из окружающей области (например, props.itemClass в следующем примере) в дополнение к любым другим параметрам, которые вы хотите.
const MyComponent = props => {
// Looks like a component, but only serves as a function.
const renderItem = ({ prop1, prop2 }) => (
<li className = {props.itemClass}> {/* <-- param from enclosing scope */}
{prop1} {prop2} {/* other code */}
</li>
);
return <ul>{props.list.map(renderItem)}</ul>;
};
Его также можно определить вне компонента, поскольку он действительно гибкий.
const renderItem = (itemClass, { prop1, prop2 }) => (
<li className = {itemClass}>
{prop1} {prop2} {/* other code */}
</li>
);
const MyComponent = props => (
<ul>
{props.list.map(item => renderItem(props.itemClass, item))}
</ul>
);
Но на этом этапе мы должны просто определить компонент React, а не подделывать его с помощью функции. Используйте React предсказуемо и в полной мере.
Очень часто встраивать JSX внутри условия или обратного вызова map.
const MyComponent = ({ itemClass }) => (
<ul>
{props.list.map(({ something, thing }) => (
<li className = {itemClass}>
{something} {thing} {/* other code */}
</li>
))}
</ul>
);
Если мы обнаружим, что копируем тот же встроенный JSX повсюду, возможно, пришло время заключить его в его собственный повторно используемый компонент.
Я так считаю. Обычно в функции рендеринга вы помещаете только некоторые вычисляемые переменные, чтобы уменьшить код в вашем JSX.