Cara membuat aplikasi React Anda merender lebih cepat

Nov 27 2022
Mengirim aplikasi dengan cepat itu mudah, mengirimkan aplikasi cepat jauh lebih sulit. Berikut beberapa tip untuk membuat aplikasi reaksi Anda merender komponen Anda lebih cepat.

Mengirim aplikasi dengan cepat itu mudah, mengirimkan aplikasi cepat jauh lebih sulit. Berikut beberapa tip untuk membuat aplikasi reaksi Anda merender komponen Anda lebih cepat.

Sementara kami mencoba mengirimkan aplikasi kami lebih cepat, kami sering lupa untuk fokus pada praktik terbaik. Setelah beberapa saat kami membuat komponen yang sangat rumit setelah Anda mengetikkan tempat kunci yang tidak perlu dirender akan dirender. Berikut daftar apa yang harus dilakukan dan apa yang tidak boleh dilakukan.

Gunakan React.Memo

Kami biasanya tidak ingin komponen kami dirender setiap kali induknya dirender. Kita dapat mengatakan Bereaksi untuk tidak merender komponen kita kecuali diperlukan.

// Wrong usage
// Without React.memo this component will get rendered each time 
// something causes its parent to render
const YourHeavyComponent = (name, title, onClick) => {
    // Render  something really heavy like whole page here
}

export default YourHeavyComponent
// Good usage
// This component will not render unless name, title or onClick changes
const YourHeavyComponent = (name, title, onClick) => {
    // Render  something really heavy like whole page here
}

export default React.memo(YourHeavyComponent)
// This component will not render unless title changes
const YourHeavyComponent = (name, title, onClick) => {
    // Render  something really heavy like whole page here
}

// This usage might better for some stations, use this second argument
// to specify which props  will cause render
export default React.memo(YourHeavyComponent, (prevProps, nextProps) => {
    return prevProps.title === nextProps.title
})

Jangan memiliki lebih dari 4 properti per komponen

Memiliki banyak props selalu bermasalah, setiap props berarti satu lagi variabel untuk dipertimbangkan dalam hal kinerja dan itu akan membuat kode Anda lebih sulit untuk dibaca dan dipelihara. Alih-alih membuat komponen dengan 10 properti, buatlah 3 bagian yang lebih kecil dengan 3–4 properti.

// this component has too many filters
// it's not a good idea to add filters inside this component
// instead we need to create a seperate component to add filter inputs
// and we can also remove title from here
const List = (title, items, sortBy, keys, filters, onFilterChange, children, pagination) => {
    // Render  something really heavy like whole page here
}
// here userslist wont rendered unless we get a new list
// pagination payload won't cause rendering in filters
const [payload, setPayload] = useState()
const [list, setList] = useState([])
return <>
    <Filters onFilterChange={setPayload} filters={payload.filters} />
    <UserList items={list}/>
    <Pagination onPaginationChange={setPayload} pagination={payload.pagination} />
</>

kait ketika Anda memiliki variabel yang akan dihitung setelah sesuatu berubah. Sangat membantu karena jika perhitungan Anda membutuhkan waktu atau setelah perhitungan Anda akan mendapatkan referensi memori yang berbeda untuk larik atau objek.

Harap jangan lupa ketika variabel Anda diubah dan Anda meneruskannya ke anak-anak, komponen anak-anak akan dirender ulang.

// here we use useMemo for purely caching purposes, if we don't use useMemo
// each time this components rendered the calculation will have to re-run 
const heavyCalculated = useMemo(() => doSomeHeavyCalculation(variable1), [variable])
// an example of wrong usage
// each time this components get rendered this
// styles variable will point to different memory address
// and this will cause rerender of YourHeavyComponent
const styles = {
  container:{
    marginLeft: left,
    marginRight: right,
    marginTop: top,
    marginBottom: bottom,
  }
}
// correct usage of useMemo
// this will cache your value and its memory point won't change
// so even if this components gets rendered your YourHeavyComponent won't be rendered again
const styles = useMemo(() => ({
  container:{
    marginLeft: left,
    marginRight: right,
    marginTop: top,
    marginBottom: bottom,
  }
}), [left, right, top, bottom])

Anda perlu menggunakan hook useCallback saat Anda akan meneruskan fungsi Anda ke komponen anak. Jangan lupa fungsi akan menunjuk ke titik memori yang berbeda setiap kali komponen Anda dirender. Kita perlu menahan panggilan balik sebelumnya di memori agar tidak berubah setiap kali kita melakukan sesuatu di komponen utama dan menyebabkan rendering pada turunannya.

// wrong usage
// each time App components get rendered for some reason
// onClickCallback will be recreated and it will point to different memory address
// so it will cause YourHeavyComponent to re render
const onClickCallback = () => {
  // do some stuff
}

return <div>
  <YourHeavyComponent onClick={onClickCallback} />
</div>

// good usage of onClickCallback
// each time App components if your variable1 don't change
// onClickCallback will point to same memory point 
// so UourHeavyCallback won't render.
const onClickCallback = () => {
  // do some stuff
}

return <div>
  <YourHeavyComponent onClick={onClickCallback} />
</div>

Kami terbiasa menggunakan pengait ini untuk memberikannya kepada anak-anak dan menggunakan instans mereka, tetapi kasus penggunaan yang tersedia tidak hanya tersedia untuk itu. Kita dapat menggunakannya sebagai semacam caching dan state mechanisim tanpa menyebabkan rerender.

// in this example we look for useRef value instead of setting
// sent reference is being used for checking if we send this message before or not
// this could hold in the state but if we put into state it will cause render
// it into state, because we don't want to re-render after we set sent.current
const sent = useRef(false)
const postMessage = useCallback(() => {
  if (!sent.current) {
    // make your api call here
    sent.current = true
  }
}, [])

Jangan pernah lupakan ini, setiap kali Anda merender komponen, variabel di dalam komponen itu akan menunjukkan alamat memori yang berbeda, ketika datang tipe primitif seperti string dan integer ini tidak akan menimbulkan masalah tetapi jika Anda bekerja dengan array, objek, dan fungsi (karena setiap fungsi sebenarnya adalah objek di balik tudung). Mari kita lihat beberapa contoh

const InlineTest = () => {
    // the usage below will cause YourHeavyComponent to render if
    // something causes InlineTest component to render
    return <YourHeavyComponent style={{
        marginLeft: 10,
        marginRight: 10
    }} />
}
const style = {
    marginLeft: 10,
    marginRight: 10
}

// We move styles outside of component
// this way style will point the same memory address regardless of 
// how many tames InlineTest gets rendered

const InlineTest = () => {
    // the usage below will cause YourHeavyComponent to render if
    // something causes InlineTest component to render
    return <YourHeavyComponent style={style} />
}

const InlineTest = () => {
    // the usage below will cause YourHeavyComponent to render if
    // something causes InlineTest component to render
    // because onClick will be assigned to a new function each time
    return <YourHeavyComponent onClick={() => {
        console.log('clicked');
    }} />;
}
import {useCallback} from "react";

const InlineTest = () => {
    // the usage below is correct way to do it
    // using useCallback will make sure onClick function
    // is the same between renders and it won't cause render in below component
    
    const onClick = useCallback(() => {
        console.log('clicked');
    }, [])
    return <YourHeavyComponent onClick={onClick} />;
}

Anda mungkin berpikir menangani formulir dalam reaksi itu mudah, tetapi izinkan saya menjamin Anda tidak. Ketika formulir Anda menjadi rumit dan Anda perlu melakukan beberapa validasi, dll, Anda akan menyebabkan terlalu banyak render. Itu sebabnya menggunakan perpustakaan yang baik itu penting. Beberapa tahun terakhir saya mencoba berbagai perpustakaan tetapi hanya ada satu yang layak disebutkan di sini; reaksi-kait-bentuk.

import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, formState: { errors } } = useForm();
  const onSubmit = data => console.log(data);


  return (
    /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register("example")} />
      
      {/* include validation with required or other standard HTML validation rules */}
      <input {...register("exampleRequired", { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}
      
      <input type="submit" />
    </form>
  );
}