رد الفعل هوكس: التخفيضات العميقة ذكاء بيانات PlatoBlockchain. البحث العمودي. عاي.

خطافات التفاعل: التخفيضات العميقة

الخطافات هي وظائف قابلة لإعادة الاستخدام. أنها تسمح لك باستخدام حالة وغيرها من الميزات (مثل طرق دورة الحياة وما إلى ذلك) دون كتابة فصل دراسي. وظائف الخطاف تتيح لنا "ربط" دورة حياة حالة رد الفعل باستخدام المكونات الوظيفية ، مما يسمح لنا بمعالجة حالة مكوناتنا الوظيفية دون الحاجة إلى تحويلها إلى مكونات فئة.

رد فعل قدم السنانير مرة أخرى في الإصدار 16.8 وتم إضافة المزيد منذ ذلك الحين. بعضها أكثر استخدامًا وشعبية من البعض الآخر ، مثل useEffect, useStateو useContext خطافات. ليس لدي شك في أنك وصلت إلى هؤلاء إذا كنت تعمل مع React.

لكن ما يهمني هو خطافات React الأقل شهرة. في حين أن جميع خطاطيف React مثيرة للاهتمام بطريقتها الخاصة ، إلا أن هناك خمسة منها أريد حقًا أن أعرضها عليك لأنها قد لا تظهر في عملك اليومي - أو ربما تفعل ذلك ومعرفتها يمنحك بعض القوى الخارقة الإضافية.

جدول المحتويات

useReducer

useReducer الخطاف هو أداة لإدارة الدولة مثل الخطافات الأخرى. على وجه التحديد ، إنه بديل لـ useState صنارة صيد.

إذا كنت تستخدم useReducer ربط لتغيير حالتين أو أكثر (أو إجراءات) ، لن تضطر إلى التلاعب بهذه الحالات بشكل فردي. الخطاف يتتبع جميع الحالات ويديرها بشكل جماعي. بمعنى آخر: إنه يدير ويعيد عرض تغييرات الحالة. على عكس useState صنارة صيد، useReducer أسهل عندما يتعلق الأمر بالتعامل مع العديد من الدول في المشاريع المعقدة.

استخدم حالات

useReducer يمكن أن تساعد في تقليل تعقيد العمل مع دول متعددة. استخدمه عندما تجد نفسك بحاجة إلى تتبع حالات متعددة بشكل جماعي ، حيث يسمح لك بمعاملة إدارة الحالة ومنطق عرض المكون كمخاوف منفصلة.

بناء الجملة

useReducer يقبل ثلاث حجج ، إحداها اختيارية:

  • وظيفة المخفض
  • initialState
  • an init وظيفة (اختياري)
const [state, dispatch] = useReducer(reducer, initialState)
const [state, dispatch] = useReducer(reducer, initialState initFunction) // in the case where you initialize with the optional 3rd argument

مثال

المثال التالي هو واجهة تحتوي على إدخال نص وعداد وزر. يؤدي التفاعل مع كل عنصر إلى تحديث الحالة. لاحظ كيف useReducer يتيح لنا تحديد حالات متعددة في وقت واحد بدلاً من إعدادها بشكل فردي.

import { useReducer } from 'react';
const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    case 'USER_INPUT':
      return { ...state, userInput: action.payload };
    case 'TOGGLE_COLOR':
      return { ...state, color: !state.color };
    default:
      throw new Error();
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, { count: 0, userInput: '', color: false })

  return (
    <main className="App, App-header" style={{ color: state.color ? '#000' : '#FF07FF'}}>
      <input style={{margin: '2rem'}}
        type="text"
        value={state.userInput}
        onChange={(e) => dispatch({ type: 'USER_INPUT', payload: e.target.value })}
      />
      <br /><br />
      <p style={{margin: '2rem'}} >{state.count}</p>
      <section style={{margin: '2rem'}}>
        <button  onClick={(() => dispatch({ type: 'DECREMENT' }))}>-</button>
        <button onClick={(() => dispatch({ type: 'INCREMENT' }))}>+</button>
        <button onClick={(() => dispatch({ type: 'TOGGLE_COLOR' }))}>Color</button>
      </section>
      <br /><br />
      <p style={{margin: '2rem'}}>{state.userInput}</p>
    </main>
  );
}
export default App;

من الكود أعلاه ، لاحظنا كيف أننا قادرون على إدارة العديد من الولايات بسهولة في المخفض (حالة التبديل) ، فهذا يدل على فائدة useReducer. هذه هي القوة التي يعطيها عند العمل في تطبيقات معقدة مع حالات متعددة.

useRef

useRef يستخدم الخطاف لإنشاء المراجع على العناصر من أجل الوصول إلى DOM. ولكن أكثر من ذلك ، تقوم بإرجاع كائن بامتداد .current الخاصية التي يمكن استخدامها طوال دورة حياة المكون بأكملها ، مما يسمح للبيانات بالاستمرار دون التسبب في إعادة التصيير. لذلك useRef تظل القيمة كما هي بين عمليات العرض ؛ لا يؤدي تحديث المرجع إلى إعادة العرض.

استخدم حالات

الوصول إلى useRef ربط عندما تريد:

  • تعامل مع DOM بالمعلومات القابلة للتغيير المخزنة.
  • الوصول إلى المعلومات من المكونات التابعة (العناصر المتداخلة).
  • ضع التركيز على عنصر.

إنها مفيدة للغاية عند تخزين البيانات القابلة للتغيير في تطبيقك دون التسبب في إعادة العرض.

بناء الجملة

useRef يقبل حجة واحدة فقط ، وهي القيمة البدائية.

const newRefComponent = useRef(initialValue);

مثال

هنا استخدمت ملف useRef و useState الخطاف لإظهار عدد المرات التي يعرض فيها التطبيق حالة محدثة عند الكتابة في إدخال نص.

import './App.css'

function App() {
  const [anyInput, setAnyInput] = useState(" ");
  const showRender = useRef(0);
  const randomInput = useRef();
  const toggleChange = (e) => {
    setAnyInput (e.target.value);
    showRender.current++;
  
  }
  const focusRandomInput = () => {
    randomInput.current.focus();
  }

  return (
    <div className="App">
      <input className="TextBox" 
        ref ={randomInput} type="text" value={anyInput} onChange={toggleChange}
      />
      <h3>Amount Of Renders: {showRender.current}</h3>
      <button onClick={focusRandomInput}>Click To Focus On Input </button>
    </div>
  );
}

export default App;

لاحظ كيف تؤدي كتابة كل حرف في حقل النص إلى تحديث حالة التطبيق ، ولكن لا يؤدي أبدًا إلى إعادة تصيير كاملة.

useImperativeHandle

هل تعرف كيف يمكن للمكون الفرعي الوصول إلى وظائف الاستدعاء التي تم تمريرها إليهم من المكون الرئيسي؟ يقوم الآباء بتمريرها عبر الدعائم ، ولكن هذا النقل "أحادي الاتجاه" بمعنى أن الوالد غير قادر على استدعاء وظيفة موجودة في الطفل.

حسنا، useImperativeHandle يجعل من الممكن للوالد الوصول إلى وظائف المكون الفرعي.

كيف يعمل هذا؟

  • يتم تحديد وظيفة في المكون الفرعي.
  • A ref يضاف في الأصل.
  • نستخدم forwardRef، مما يسمح ref التي تم تعريفها لتمريرها إلى الطفل.
  • useImperativeHandle يعرض وظائف الطفل عبر ref.

استخدم حالات

useImperativeHandle يعمل بشكل جيد عندما تريد أن يتأثر المكون الرئيسي بالتغييرات في الطفل. لذلك ، قد تكون أشياء مثل التركيز المتغير ، والتزايد والتناقص ، والعناصر غير الواضحة مواقف تجد فيها نفسك تصل إلى هذا الخطاف حتى يمكن تحديث الوالد وفقًا لذلك.

بناء الجملة

useImperativeHandle (ref, createHandle, [dependencies])

مثال

في هذا المثال ، لدينا زرين ، أحدهما في المكون الرئيسي والآخر في الطفل. يؤدي النقر فوق الزر الأصل إلى استرداد البيانات من الطفل ، مما يسمح لنا بمعالجة المكون الرئيسي. تم إعداده بحيث لا يؤدي النقر فوق الزر الفرعي إلى تمرير أي شيء من المكون الرئيسي إلى الطفل للمساعدة في توضيح كيفية تمرير الأشياء في الاتجاه المعاكس.

// Parent component
import React, { useRef } from "react";
import ChildComponent from "./childComponent";
import './App.css';

function useImperativeHandle() {
  const controlRef = useRef(null);
  return (
    onClick={
      () => {
        controlRef.current.controlPrint();
      }
    }
    >
    Parent Box
  );
}
export default useImperativeHandle;
// Child component
import React, { forwardRef, useImperativeHandle, useState } from "react";

const ChildComponent = forwardRef((props, ref) => {
  const [print, setPrint] = useState(false);
  useImperativeHandle(ref, () => ({
    controlPrint() 
    { setPrint(!print); },
  })
  );

  return (
    <>
    Child Box
    { print && I am from the child component }
  );
});

export default ChildComponent;

الناتج

useMemo

useMemo هي واحدة من أقل خطاطيف React استخدامًا ولكنها الأكثر إثارة للاهتمام. يمكنه تحسين الأداء وتقليل زمن الوصول ، لا سيما في العمليات الحسابية الكبيرة في تطبيقك. كيف ذلك؟ في كل مرة يتم فيها إعادة تصيير تحديث حالة المكون ومكوناته ، يتم إعادة تصيير ملف useMemo الخطاف يمنع React من الاضطرار إلى إعادة حساب القيم.

ترى ، تستجيب الوظائف لتغيرات الحالة. ال useMemo يأخذ الخطاف وظيفة و تُرجع القيمة المرجعة لتلك الدالة. يخزن هذه القيمة مؤقتًا لمنع إنفاق جهد إضافي لإعادة عرضها ، ثم يعيدها عندما تتغير إحدى التبعيات.

هذه العملية تسمى التحفيظ وهو ما يساعد على تعزيز الأداء من خلال تذكر القيمة من طلب سابق بحيث يمكن استخدامها مرة أخرى دون تكرار كل هذه الحسابات.

استخدم حالات

ستكون أفضل حالات الاستخدام في أي وقت تعمل فيه مع عمليات حسابية ثقيلة حيث تريد تخزين القيمة واستخدامها في تغييرات الحالة اللاحقة. يمكن أن يكون فوزًا رائعًا في الأداء ، ولكن استخدامه كثيرًا يمكن أن يكون له تأثير معاكس تمامًا عن طريق استنزاف ذاكرة التطبيق الخاص بك.

بناء الجملة

useMemo( () => 
  { // Code goes here },
  []
)

مثال

عند النقر فوق الزر ، يشير هذا البرنامج الصغير إلى متى يكون الرقم زوجيًا أو فرديًا ، ثم يقوم بتربيع القيمة. لقد أضفت الكثير من الأصفار إلى الحلقة لزيادة قدرتها الحسابية. تقوم بإرجاع القيمة بالثواني المنسكبة ولا تزال تعمل بشكل جيد بسبب useMemo صنارة صيد.

// UseMemo.js
import React, { useState, useMemo } from 'react'

function Memo() {
  const [memoOne, setMemoOne] = useState(0);
  const incrementMemoOne = () => { setMemoOne(memoOne + 1) }
  const isEven = useMemo(() => { 
    let i = 0 while (i < 2000000000) i++ return memoOne % 2 === 0
  },
  [memoOne]);
  
  const square = useMemo(()=> { 
    console.log("squared the number"); for(var i=0; i < 200000000; i++);
    return memoOne * memoOne;
  },
  [memoOne]);

  return (
    Memo One - 
    { memoOne }
    { isEven ? 'Even' : 'Odd' } { square } 
  );
}
export default Memo

الناتج

useMemo يشبه قليلا useCallback الخطاف ، ولكن الاختلاف هو ذلك useMemo يمكن تخزين القيمة المحفوظة من وظيفة ، حيث useCallback يخزن الوظيفة نفسها.

useCallback

useCallback الخطاف هو عنصر آخر مثير للاهتمام وكان القسم الأخير نوعًا من تنبيه المفسد لما يفعله.

كما رأينا للتو ، useCallback يعمل مثل useMemo ربط في أن كلاهما يستخدم ذاكرة التخزين المؤقت لشيء ما لاستخدامه لاحقًا. في حين useMemo يخزن حساب الوظيفة كقيمة مخزنة مؤقتًا ، useCallback يخزن ويعيد وظيفة.

استخدم حالات

اعجاب useMemo, useCallback هو تحسين أداء رائع من حيث أنه يخزن ويعيد رد نداء مذكّر وأي من تبعياته دون إعادة تصيير.

بناء الجملة

const getMemoizedCallback = useCallback (
  () => { doSomething () }, []
);

مثال


{ useCallback, useState } from "react";
import CallbackChild from "./UseCallback-Child";
import "./App.css"

export default function App() {
  const [toggle, setToggle] = useState(false);
  const [data, setData] = useState("I am a data that would not change at every render, thanks to the useCallback");
  const returnFunction = useCallback(
    (name) => 
    { return data + name; }, [data]
  );
  return (
    onClick={() => {
      setToggle(!toggle);
    }}
    >
    {" "}

    // Click To Toggle
    { toggle && h1. Toggling me no longer affects any function } 
  ); 
}
// The Child component
import React, { useEffect } from "react";

function CallbackChild(
  { returnFunction }
) {
  useEffect(() => 
    { console.log("FUNCTION WAS CALLED"); },
    [returnFunction]);
  return { returnFunction(" Hook!") };
}
export default CallbackChild;

الناتج

الأفكار النهائية

هناك نذهب! لقد نظرنا للتو إلى خمسة خطاطيف React سهلة الاستخدام والتي أعتقد أنها غالبًا ما يتم تجاهلها. كما هو الحال مع العديد من الجولات مثل هذه ، نحن مجرد خدش سطح هذه الخطافات. لكل منهم الفروق الدقيقة والاعتبارات الخاصة به التي يجب مراعاتها عند استخدامها. لكن آمل أن يكون لديك فكرة جيدة عالية المستوى عما هي عليه ومتى قد يكون مناسبًا بشكل أفضل من خطاف آخر قد تصل إليه كثيرًا.

أفضل طريقة لفهمها تمامًا هي من خلال الممارسة. لذلك أشجعك على التدرب على استخدام هذه الروابط في تطبيقك من أجل فهم أفضل. لذلك ، يمكنك الحصول على مزيد من التعمق من خلال الاطلاع على الموارد التالية:

الطابع الزمني:

اكثر من الخدع المغلق