想象一個簡單的表單,它呈現多個應用一些布局調整的自定義組件。
自定義組件是:<UsernameInput />, <PasswordInput />, <DateTimePicker />, <FancyButton />,<Checkbox />
表單組件的 JSX 如下所示:
return (
<View style={globalStyles.flex}>
<View style={styles.inputsContainer}>
<UsernameInput
... // a lot of props
/>
<PasswordInput
... // a lot of props
/>
<DateTimePicker
... // a lot of props
/>
</View>
<View style={styles.footer}>
<Checkbox />
<FancyButton type="submit" onPress={...} />
</View>
</View>
);
如果我們嘗試將組件的渲染方法拆分為多個內部子渲染函式會怎樣?
const LoginForm = ({ ... }) => {
...
/**
* Renders the inputs of the form.
*
* @returns {React.ReactElement} The inputs.
*/
const renderInputs = () => (
<View style={styles.inputsContainer}>
<UsernameInput
... // a lot of props
/>
<PasswordInput
... // a lot of props
/>
<DateTimePicker
... // a lot of props
/>
</View>
);
/**
* Renders the submit button.
*
* @returns {React.ReactElement} The footer of the form.
*/
const renderFooter = () => (
<View style={styles.footer}>
<Checkbox />
<FancyButton type="submit" onPress={...} />
</View>
);
return (
{renderInputs()}
{renderFooter()}
);
};
那些輔助方法回傳 JSX!它們不是簡單的普通函式,它們是組件!我們在每次渲染中重新創建組件!
為了處理這個問題,我所做的是將內部函式轉換為內部記憶組件,如下所示:
/**
* Renders the submit button.
*
* @type {React.FC}
* @returns {React.ReactElement} The footer of the form.
*/
const Footer = useCallback(() => (
<View style={styles.footer}>
<Checkbox />
<FancyButton type="submit" onPress={...} />
</View>
), [deps]);
return (
<View style={globalStyles.flex}
<Inputs />
<Footer />
</View>
);
這被認為是反模式嗎?我的意思是,當沒有理由在應用程式的全域范圍內(在新模塊中或在組件之外)創建新組件時,我們是否應該避免拆分 JSX?
uj5u.com熱心網友回復:
這被認為是反模式嗎?
useCallback如果您不將這些函式作為道具提供給其他組件,在它們的道具不變時不重新渲染來優化它們的渲染,那么在這些函式上使用是沒有意義的。(很多人誤解useCallback了,有點微妙。)每次你仍然useCallback在重新創建它們(你必須創建函式來傳遞它),你只是在做更多的作業(處理deps)來決定是否使用新創建的函式或先前創建的函式。這是沒有目的的開銷,而不是什么目的useCallback。的目的useCallback是創建穩定或盡可能穩定的函式參考,以傳遞給子組件,如果您不更改它們接收的函式,這些子組件可能能夠避免重新渲染。
相反,要么:
在您的模塊中制作這些組件(或只是幫助函式,取決于)。(如果它們僅由您的組件使用,則無需匯出它們。)這樣,它們只創建一次(在加載模塊時)。
如果你想一想,這就像任何其他變得太大的函式一樣:你把它分成幾部分,然后把這些部分放入你呼叫的更小的函式中。相同的概念。
要么
在第一次渲染時創建一次函式(當然要確保它們不會關閉所需的任何東西;而是將其傳遞給它們),將結果存盤在 ref via 上的物件上
useRef:const fnRef = useRef(null); if (!fn.Ref.current) { fnRef.current = { Footer: /*...*/, SomethingElse: /*...*/, // ... }; } const { Footer, SomethingElse /*, ...*/ } = fnRef.current; // ...那樣的話,它們真的只在裝載時被創建一次。
我會強烈傾向于#1。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/451956.html
標籤:javascript 反应 反应式
上一篇:當應用程式在GooglePlayStore上發布時,API中的資料不會從主機中獲取
下一篇:i18nextundefined不是物件(評估'_i18next.default.services.formatter.add')
