react性能優化之render

兩個相互關聯的組件想要共享狀態,咱們會想到提高狀態到倆組件最近的父級節點

1、一般我會會在父級設置狀態,兩個子組件共享父組件的狀態,一般的作法是:
 1. 父組件設置狀態,倆子組件接收props 🤔
... 這種狀況會是:其中任何一個子組件的改變,都會形成整個父級組件的重渲染 render。
 2. 父組件不設置狀態,倆子組件不接收props, 組件樹的頂層使用 React Context
來共享數據 🤔
... 這種狀況會是:只要提供給 Provider 的值發生變化,全部消費到了 Provider 的後代組件都會發生重渲染 render。

2、咱們要怎樣才能共享狀態,又不會形成重渲染 render🤔️,這裏咱們就要用的 useRef

「當 ref 對象內容發生變化時,useRef 並不會通知變動。變動 .current 屬性不會引起組件
從新渲染。」 —— React 文檔
 1. 父組件建立ref 對象,倆子組件接收父組件建立的ref,這樣子組件拿到變動 .current
 ,下面經過一個🌰:(這裏咱們經過Provider的)
一個簡單的星期英文翻譯:

translateContext.jsxhtml

import { createContext, useContext, useRef } from "react";

export const translateContext = createContext({});

export const useTranslateContext = () => useContext(translateContext);


export const TranslateProvider = ({ children }) => {
    const translateRef = useRef({});
    return (
        <translateContext.Provider value={{translateRef}}>
            {children}
        </translateContext.Provider>
    )
}
複製代碼

translate.jsxreact

import { useState } from 'react';
import { TranslateProvider, useTranslateContext } from './translateContxt';
const dict = {
    '週一': 'Monday',
    '週二': 'Tuesday',
    '週三': 'Wednesday',
    '週四': 'Thursday',
    '週五': 'Friday',
    '週六': 'Saturday',
    '週日': 'Sunday',
}

const CnTranslate = () => {
    const { translateRef } = useTranslateContext();
    const onChange = (e) => {
        const { value } = e.target;
        translateRef.current.value = value;
    }
    const translate = () => {
        translateRef.current.setTranslate(false);
        setTimeout(() => {
            translateRef.current.setTranslate(true)
        }, 100)
    }
    return (
        <div style={{ flex: '1', background: "#fff", margin: '10px', textAlign: 'center' }}>
            <input type="text" onChange={onChange}/>{' '}
            <button onClick={translate}>翻譯</button>
        </div>
    )
}

const EnTranslate = () => {
    const [translate, setTranslate] = useState(false);
    const { translateRef } = useTranslateContext();
    translateRef.current.setTranslate = setTranslate;
    return (
        <div style={{ flex: '1', background: "#fff", margin: '10px', textAlign: 'center'}}>
            {translate && (<span>{dict[translateRef.current.value]}</span>)}
        </div>
    )
}


const Translate = () => {
    return (
        <div style={{ display: 'flex', lineHeight: '160px', width: '600px', background: "#4787de", margin: '50px'}}>
            <TranslateProvider>
                <CnTranslate/>
                <EnTranslate/>
            </TranslateProvider>
        </div>
    )
}

export default Translate;
複製代碼
相關文章
相關標籤/搜索