Ref дамжуулах

Ref дамжуулах гэдэг нь ref -ыг ѳѳрийн болон түүний дотор орших компонентуудад автоматаар дамжуулах арга юм. Аппликейшний ихэнх компонентод шаардлагагүй боловч зарим тохиолдолд хэрэгтэй байдаг, тухайлбал дахин ашиглагдах компонент сан үүсгэх үед ч юм уу. Ѳргѳн хэрэглээг доор дурьдав.

Ref-ыг DOM доторх компонентруу дамжуулах

FancyButton гэх натив товч рендерлэдэг компонент байлаа гэвэл:

function FancyButton(props) {
  return (
    <button className="FancyButton">
      {props.children}
    </button>
  );
}

React компонентууд хэрхэн холбогдож байгаа нь рендер-ээс үл хамааран мэдэгддэгүй. Ѳѳр компонентууд FancyButton ашиглаж байгаа үед ихэнх тохиолдолд ref -ыг DOM элементрүү авах шаардлагагүй. Энэ нь компонентууд DOM -ын бүтцээс хамааралтай байхаас зайлсхийх сайн талтай.

Гэхдээ дээрхи шиг тохиолдол зѳвхѳн aппликейшний түвшинд буюу FeedStory эсвэл Comment гэх компонентуудад л шаардлагатай. Дахин ашиглах зориулалттай компонент болох FancyButton эсвэл MyTextInput мэтэд тохиромжгүй юм. Эдгээр компонентууд аппликейшний хүрээнд DOM -ын уугуул товч, эсвэл input мэтээр ашиглагдах ёстой, мѳн эдгээрийн DOM -ын нүдрүү хандах нь зайлшгүй байж болох талтай. Жишээ нь: focus, selection эсвэл animation хийхэд г.м

Ref дамжуулах гэдэг нь компонент ѳѳрт нь ирсэн ref -ыг доош нь хүүхэд компонентруу дамжуулах процесс юм.

Доорх жишээ дээр FancyButton React.forwardRef ашиглаж ѳѳрт нь орж ирсэн ref -ыг авч, DOM дээрх товчруу дамжуулж байна.

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

Ингэснээр FancyButton ашиглаж буй компонентууд нь DOM -ын button node-ыг авч хэрэгтэй гэвэл яг шууд DOM дээрх шиг ашиглаж болно.

Дээрхи жишээ дээр болсон зүйлсийг алхам алхамаар сийрүүлбэл:

  1. Бид React.createRef дуудаж ref хувьсагчид оноож React ref үүсгэнэ.
  2. ref -ыг <FancyButton ref={ref}> руу JSX аттрибут болгон дамжуулна.
  3. React ref -ыг (props, ref) => ... функцийн доторх forwardRef рүү 2 дахь аргумент болгон дамжуулна.
  4. Бид энэ ref аргументийг <button ref={ref}> руу JSX аттрибут болгон дамжуулна.
  5. ref бэлэн болоход ref.current нь DOM дээрх <button> -руу заах юм.

Тэмдэглэл

2 дахь ref аргумент нь зѳвхѳн компонентийг React.forwardRef гэж зарласан үед боломжтой. Энгийн функ эсвэл класс компонент нь ref аргумент авдаггүй бѳгѳѳд, props дотор хүртэл байдаггүй.

Ref дамжуулах нь DOM компонентоор хязгаарлагдахгүй. Класс компонентруу хүртэл дамжуулж болно.

Компонент сан бүтээгчдэд анхаарах зүйлс

Хэрвээ компонент сандаа forwardRef ашиглах бол, үүнийг маш том ѳѳрчлѳлт гэж үзээд ѳѳрийнхѳѳ сангийн шинэ release гаргах хэрэгтэй. Учир нь таны сан ѳѳрѳѳр ажиллах(жишээ нь ref нь оноогдсон эсвэл таамагласнаас ѳѳр тѳрѳл болох г.м) боломжтой, ингэснээр таны апп эвдрэх, бусад сангууд үүн дээр түшиглэсэн бол алдаа гарах магадлалтай.

Нѳгѳѳтэйгүүр React.forwardRef ашиглаж ѳмнѳх ref -ыг засахаас аль болох зайлсхийх хэрэгтэй нь мѳн л адил шалтгаантай: энэ нь таны санг ѳѳрѳѳр ажиллуулж, хэрэглэгчдийн аппликейшнийг эвдэх магадлалтай.

Дээд түвшний компонентуудад ref дамжуулах нь

Энэхүү техник нь дээд-түвшний компонент(HOC) ашиглахад зориулсан Энгийн жишээ болгон компонентийн пропс-ыг консолд хэвлэдэг HOC:

function logProps(WrappedComponent) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return LogProps;
}

“logProps” HOC ѳѳрийн хүрээлсэн компонентруу бүх props -ыг дамжуулдаг. Ингэснээр рендер хийгдэх гаралт нь адилхан харагдана. Жишээ нь бид энэ HOC -ыг ашиглан “fancy button” руу дамжуулсан бүх пропс-ыг харж болох нь:

class FancyButton extends React.Component {
  focus() {
    // ...
  }

  // ...
}

// Rather than exporting FancyButton, we export LogProps.
// It will render a FancyButton though.
export default logProps(FancyButton);

Нэг анхаарах зүйл нь: refs дамжуулагдахгүй байгаа. Учир нь ref нь проп биш юм. key -г React ѳѳрѳѳ зохицуулдаг шиг. Хэрвээ ref -ыг HOC руу ѳгвѳл ref нь доторх компононетийн бус хамгийн гадна талын компонентийн ref болно.

Тэгэхээр манай FancyButton компонентод зориулагдсан ref LogProps компонентод очих нь:

import FancyButton from './FancyButton';

const ref = React.createRef();

// The FancyButton component we imported is the LogProps HOC.
// Even though the rendered output will be the same,
// Our ref will point to LogProps instead of the inner FancyButton component!
// This means we can't call e.g. ref.current.focus()
<FancyButton
  label="Click Me"
  handleClick={handleClick}
  ref={ref}
/>;

Аз болж, бид ref-ыг доторх FancyButton компонентруу React.forwardRef API ашиглан тусд нь дамжуулж болдог. React.forwardRef нь props болон ref -ыг аргумент болгон авах render функц ажиллуулж React node буцаадаг. Жишээ нь:

function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const {forwardedRef, ...rest} = this.props;

      // Assign the custom prop "forwardedRef" as a ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }

  // Note the second param "ref" provided by React.forwardRef.
  // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
  // And it can then be attached to the Component.
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}

DevTools дотор дурын нэр гаргах нь

React.forwardRef нь render функц авдаг. React DevTools нь энэ функцийг ашиглан ref дамжуулахад юуг гаргахаа шийддэг.

Жишээ нь, доорхи компонент нь ForwardRef гэж гаргах нь:

const WrappedComponent = React.forwardRef((props, ref) => {
  return <LogProps {...props} forwardedRef={ref} />;
});

Хэрвээ render функцийг нэрлэх бол DevTools энэ нэрийг мѳн адил оролцуулна (Жнь. ”ForwardRef(myFunction)”):

const WrappedComponent = React.forwardRef(
  function myFunction(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }
);

Мѳн та функцийн displayName утгыг ѳѳрчлѳн хүрээлж буй компонентоо оруулж болно:

function logProps(Component) {
  class LogProps extends React.Component {
    // ...
  }

  function forwardRef(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }

  // Give this component a more helpful display name in DevTools.
  // e.g. "ForwardRef(logProps(MyComponent))"
  const name = Component.displayName || Component.name;
  forwardRef.displayName = `logProps(${name})`;

  return React.forwardRef(forwardRef);
}