ویژگی‌های (prop) رندر React

گردآوری و تالیف : عرفان کاکایی
تاریخ انتشار : 22 شهریور 1397
دسته بندی ها : جاوا اسکریپت

ویژگی‌های رندر، (Render prop) یک روش تقریبا جدید برای به اشتراک گذاری / استفاده مجدد کد در React است. React router و Downshift کتابخانه‌هایی هستند که از ویژگی‌های رندر استفاده می‌کنند.

یک ویژگی رندر چیست؟ اساسا یک ویژگی رندر، ویژگی‌ای به همراه یک تابع به عنوان مقدارش است. این ویژگی رندر، کامپوننت را از آنچه که باید رندر کند، مطلع می‌سازد. طبق اسناد خود React، یک کامپوننت به همراه یک ویژگی رندر، یک تابع را می‌گیرد که یک عنصر React را بر می‌گرداند و به جای پیاده‌سازی منطق رندر خود، آن را فراخوانی می‌کند.

حال که می‌دانیم ویژگی‌های رندر چیستند، بیایید آن‌ها را در حین عمل ببینیم.

با استفاده از ویژگی‌های رندر، از کد خود مجددا استفاده کنید

اساسا، کاری که ما می‌خواهیم انجام دهیم، به اشتراک گذاری state / رفتار یک کامپوننت موجود با دیگر کامپوننت‌ها که همان state را نیاز دارند است.

پس برای مثال، یک برنامه ساده داریم که حرکت موس را بر روی صفحه دنبال می‌کند:

import React from 'react'

import ReactDOM from 'react-dom'



const App = React.createClass({

  state = { x: 0, y: 0 }



  handleMouseMove = (event) => {

    this.setState({

      x: event.clientX,

      y: event.clientY

    })

  },



  render() {

    const { x, y } = this.state



    // همینطور که موس در صفحه حرکت می‌کند، کامپوننت موقعیت آن را نشان می‌دهد.

    return (

      <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

        <h1>The mouse position is ({x}, {y})</h1>

      </div>

    )

  }

})

ReactDOM.render(<App/>, document.getElementById('app'))

اگر می‌خواستید این رفتار را با دیگر کامپوننت‌ها به اشتراک بگذارید، چگونه از ویژگی رندر برای جمع‌بندی آن استفاده می‌کنید؟

import React from 'react'

import ReactDOM from 'react-dom'

import PropTypes from 'prop-types'



class Mouse extends React.Component {

  static propTypes = {

    render: PropTypes.func.isRequired

  }



  state = { x: 0, y: 0 }



  handleMouseMove = (event) => {

    this.setState({

      x: event.clientX,

      y: event.clientY

    })

  }



  render() {

    return (

      <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

        {this.props.render(this.state)}

      </div>

    )

  }

}



class App extends React.Component {

  render() {

    return (

      <div style={{ height: '100%' }}>

        <Mouse render={({ x, y }) => (

          <h1>The mouse position is ({x}, {y})</h1>

        )}/>

      </div>

    )

  }

}



ReactDOM.render(<App/>, document.getElementById('app'))

کاری که در اینجا انجام داده‌ایم، این است که یک کامپوننت‌ جدید به نام <Mouse> ساخته‌ایم، که یک ویژگی رندر را می‌گیرد. مقدار این ویژگی، یک تابع است. سپس این ویژگی در رندر <Mouse> استفاده شده است، تا تعیین کند که چه چیزی باید رندر شود.

نکته: state متعلق به <Mouse>، با استفاده از ویژگی رندر در معرض کامپوننت <App> قرار داده شده است. این مسئله کامپوننت App را قادر می‌سازد تا هر چیزی که می‌خواهد را با آن state رندر کند.

ویژگی رندر در <Mouse> آن را قادر می‌سازد تا به صورت دینامیک تعیین کند که چه چیزی باید رندر شود. از این رو، کاملا قابل حمل است و می‌توانیم از آن برای موارد زیادی استفاده کنیم.

import React from 'react'

import ReactDOM from 'react-dom'

import PropTypes from 'prop-types'

import cat from "./cat.png";



class Mouse extends React.Component {

  static propTypes = {

    render: PropTypes.func.isRequired

  }



  state = { x: 0, y: 0 }



  handleMouseMove = (event) => {

    this.setState({

      x: event.clientX,

      y: event.clientY

    })

  }



  render() {

    console.log("mouse", this.state)

    return (

      <div onMouseMove={this.handleMouseMove}>

        {this.props.render(this.state)}

      </div>

    )

  }

}



class Cat extends React.Component {

  render() {

    const {x, y} = this.props.mouse;



    return (

      <img src={cat} style={{ position: 'absolute', left: x, top: y, height: 50 }} />

    );

  }

}



class App extends React.Component {

  render() {

    return (

      <div>

        <div>

          <Mouse render={({ x, y }) => (

            <h1>The mouse position is ({x}, {y})</h1>

          )}/>

        </div>



        // موارد استفاده مختلف برای موقعیت موس

        <div>

          <Mouse render={({ x, y }) => (

            <Cat mouse={{ x, y }} />

          )}/>

        </div>

      </div>

    )

  }

}



export default App;

ما یک کامپوننت جدید به نام <Cat> اضافه کردیم که از رفتار موقعیت موس برای حرکت دادن یک گربه بر روی صفحه استفاده می‌کند.

به یاد داشته باشید که ما نمی‌خواهیم از ویژگی‌ای به نام render استفاده کنیم. تا زمانی که از یک ویژگی استفاده کنیم که مقدارش یک تابع است، که کامپوننت از آن برای این استفاده می‌کند که تعیین کند چه چیزی را باید رندر کند، ما در حال استفاده از الگوی render prop (ویژگی رندر) خواهیم بود. با توجه به این مسئله، می‌توانیم از ویژگی‌های فرزند (child prop) استفاده کنیم:

<Mouse children={({ x, y }) => (

  <p>The mouse position is {x}, {y}</p>

)}/>

این معمولا در قالب مفهوم «فرزندان به عنوان یک تابع» (Children as a function) شناخته می‌شود و دقیقا به مانند render prop است. React-motion از این مفهموم استفاده می‌کند.

نتیجه گیری

کار ما به اتمام رسیده است. ویژگی‌های رندر استفاده مجدد از کد را بسیار ساده می‌کنند. به یاد داشته باشید، هر زمان که کامپوننتی می‌سازیم، می‌خواهیم در حد ممکن قابلیت استفاده مجدد را داشته باشد.

منبع

مقالات پیشنهادی

چگونه از Bootstrap به همراه React استفاده کنیم؟

با محبوبیت روز افزون برنامه‌های تک صفحه‌ای در سال‌های اخیر، تعداد زیادی فریم‌وورک جاوااسکریپت frontend مانند Angular، React، VueJS و Ember پدید آمده‌ا...

تجربه استفاده از React Native در Airbnb : بخش اول

در سال ۲۰۱۶ شرکت Airbnb تصمیم به استفاده از ری‌اکت نیتیو گرفتند. حال پس از گذشت دو سال آن‌ها قصد دارند تجربه‌شان در رابطه با استفاده از این فریمورک را...

انتقال state میان کامپوننت ها در reactjs

در این پست، نحوه انتقال state بین کامپوننت‌های مختلف در React.js را توضیح خواهم داد. ما برنامه ساده‌ای به نام «چند کتاب خواندید؟» می‌سازیم. در اینجا،...

تجربه استفاده از React Native در Airbnb: ری‌اکت نیتیو در حال غروب کردن

به دلیل وجود مشکلات تکنیکی و سازمانی بسیار، ما تلاش داریم که به استفاده از ری‌اکت نیتیو خاتمه دهیم و تمام تلاش‌های‌مان را در پلتفرم نیتیو و اصلی قرار...