React with JSX یک ابزار فوق العاده برای ساخت قطعات با کاربری آسان است. اجزای حروف تایپ باعث می شود که توسعه دهندگان اجزای شما را در برنامه های خود ادغام کرده و API های شما را کشف کنند. با سه API کمتر شناخته شده React آشنا شوید که می توانند اجزای شما را به سطح بعدی برسانند و در این مقاله به شما کمک می کنند تا کامپوننت های React را بهتر بسازید.
آیا تا به حال استفاده کرده اید React.createElement
به طور مستقیم؟ چه خبر React.cloneElement
؟ React فراتر از تبدیل JSX شما به HTML است. بسیار بیشتر ، و برای اینکه بتوانید دانش خود را در مورد API های کمتر شناخته شده (اما بسیار مفید) که کتابخانه React با آن حمل می کند ، ارتقا دهید. ما قصد داریم به تعدادی از آنها و برخی موارد استفاده از آنها بپردازیم که می تواند ادغام و مفید بودن اجزای شما را به شدت افزایش دهد.
در این مقاله ، ما به چند API مفید React می پردازیم که به طور معمول شناخته شده نیستند اما برای توسعه دهندگان وب بسیار مفید هستند. خوانندگان باید با نحو React و JSX تجربه داشته باشند ، دانش Typescript مفید است اما لازم نیست. خوانندگان هر آنچه را که باید بدانند برای تقویت اجزای React هنگام استفاده از آنها در برنامه های React ، از بین خواهند برد.
React.cloneElement
شاید اکثر توسعه دهندگان نام آن را نشنیده باشند cloneElement
یا تا به حال از آن استفاده کرده است نسبتاً اخیراً برای جایگزینی آن معرفی شد اکنون منسوخ شده است cloneWithProps
عملکردبه cloneElement
یک عنصر را کلون می کند ، همچنین به شما امکان می دهد لوازم جدید را با عنصر موجود ادغام کنید ، آنها را تغییر دهید یا آنها را به صلاحدید خود لغو کنید. این گزینه های بسیار قدرتمندی را برای ایجاد API های سطح جهانی برای اجزای عملکردی باز می کند. یه نگاهی به امضا بنداز
function cloneElement( element, props?, ...children)
در اینجا نسخه فشرده تایپ تایپ است:
function cloneElement(
element: ReactElement,
props?: HTMLAttributes,
...children: ReactNode[]): ReactElement
می توانید یک عنصر را بگیرید ، آن را اصلاح کنید ، حتی فرزندان آن را نادیده بگیرید و سپس آن را به عنوان یک عنصر جدید بازگردانید. به مثال زیر توجه کنید. فرض کنید می خواهیم a ایجاد کنیم TabBar جزء پیوندها ممکن است چیزی شبیه به این باشد
export interface ITabbarProps {
links: {title: string, url: string}[]
}
export default function Tabbar(props: ITabbarProps) {
return (
<>
{props.links.map((e, i) =>
<a key={i} href={e.url}>{e.title}</a>
)}
</>
)
}
TabBar لیستی از پیوندها است ، اما ما به روشی برای تعریف دو قطعه داده ، عنوان پیوند و URL نیاز داریم. بنابراین ما می خواهیم یک ساختار داده با این اطلاعات منتقل شود. بنابراین توسعه دهنده ما کامپوننت ما را چنین می کند.
function App() {
return (
<Tabbar links={[
{title: 'First', url: "https://smashingmagazine.com/first"},
{title: 'Second', url: '/second'}]
} />
)
}
این عالی است ، اما اگر کاربر بخواهد رندر کند ، چه؟ button
عناصر به جای a
عناصر؟ خوب ، ما می توانیم یک ویژگی دیگر اضافه کنیم که به مولفه می گوید چه نوع عنصری را باید ارائه دهد.
اما می بینید که چگونه این کار به سرعت سخت می شود ، ما باید از ویژگی های بیشتر و بیشتر برای رسیدگی به موارد مختلف استفاده و موارد لبه برای حداکثر انعطاف پذیری پشتیبانی کنیم.
در اینجا یک راه بهتر ، استفاده از React.cloneElement
به
ما ابتدا با تغییر رابط کاربری خود به مرجع ReactNode
نوع این یک نوع عمومی است که شامل هر چیزی است که React می تواند ارائه دهد ، معمولاً JSX Elements ، اما همچنین می تواند رشته و حتی باشد null
به این برای تعیین این نکته که می خواهید اجزای React یا JSX را به عنوان آرگومان های داخلی بپذیرید مفید است.
export interface ITabbarProps {
links: ReactNode[]
}
اکنون ما از کاربر می خواهیم برخی از React Elements را در اختیار ما قرار دهد و آنها را آنطور که می خواهیم ارائه می دهیم.
function Tabbar(props: ITabbarProps) {
return (
<>
{props.links.map((e, i) =>
e // simply return the element itself
)}
</>
)
}
این کاملاً معتبر است و عناصر ما را رندر می کند. اما ما دو مورد را فراموش می کنیم. برای یکی، key
! ما می خواهیم کلیدها را اضافه کنیم تا React بتواند لیست های ما را به طور موثر ارائه کند. ما همچنین می خواهیم عناصر خود را تغییر دهیم تا تغییرات لازم را ایجاد کنیم تا با ظاهر ما مطابقت داشته باشد ، مانند className
، و غیره
ما می توانیم این کارها را با React.cloneElement
، و عملکرد دیگر React.isValidElement
برای بررسی استدلال مطابق با آنچه ما انتظار داریم!
React.isValidElement
این تابع برمی گردد true
اگر یک عنصر یک عنصر React معتبر باشد و React می تواند آن را رندر کند. در اینجا نمونه ای از اصلاح عناصر از مثال قبلی آورده شده است.
function Tabbar(props: ITabbarProps) {
return (
<>
{props.links.map((e, i) =>
isValidElement(e) && cloneElement(e, {key: `${i}`, className: 'bold'})
)}
</>
)
}
در اینجا ما به هر عنصری که از آن عبور می کنیم یک کلید کلیدی اضافه می کنیم و هر پیوند را همزمان پررنگ می کنیم! اکنون می توانیم React Elements دلخواه را به عنوان مواردی مانند موارد زیر بپذیریم:
function App() {
return (
<Tabbar links={[
<a href="https://smashingmagazine.com/first">First</a>,
<button type="button">Second</button>
]} />
)
}
ما می توانیم هر یک از لوازم جانبی تنظیم شده بر روی یک عنصر را نادیده بگیریم و به راحتی انواع مختلف عناصر را بپذیریم که باعث می شود اجزای ما بسیار انعطاف پذیر و آسان برای استفاده باشند.
مزیت اینجا این است که بخواهیم سفارشی را تنظیم کنیم onClick
کنترل کننده دکمه ما ، ما می توانیم این کار را انجام دهیم. پذیرش خود عناصر React به عنوان استدلال راهی قدرتمند برای ایجاد انعطاف پذیری در طراحی اجزای شما است.
useState
تابع تنظیم کننده
از قلاب استفاده کنید! این useState
hook بسیار مفید است و یک API فوق العاده برای ایجاد سریع حالت در اجزای شما است ، مانند:
const [myValue, setMyValue] = useState()
به دلیل زمان اجرای جاوا اسکریپت ، ممکن است دچار سکسکه شود. تعطیلی ها را به خاطر دارید؟
در شرایط خاص ، یک متغیر ممکن است به دلیل زمینه ای که در آن قرار دارد ، مانند در حلقه های معمولی یا رویدادهای ناهمزمان ، مقدار درستی نباشد. این به دلیل محدوده لغوی است. هنگامی که یک تابع جدید ایجاد می شود ، دامنه لغوی حفظ می شود. از آنجا که هیچ تابع جدید وجود ندارد ، محدوده لغوی از newVal
حفظ نمی شود ، و بنابراین مقدار در واقع در زمان استفاده حذف می شود.
setTimeout(() => {
setMyValue(newVal) // this will not work
}, 1000)
آنچه شما باید انجام دهید این است که از تنظیم کننده به عنوان یک تابع استفاده کنید. با ایجاد یک تابع جدید ، مرجع متغیرها در محدوده واژگانی حفظ می شود و currentVal توسط خود React useState Hook منتقل می شود.
setTimeout(() => {
setMyValue((currentVal) => {
return newVal
})
}, 1000)
این امر اطمینان حاصل می کند که مقدار شما به درستی به روز می شود زیرا تابع تنظیم کننده در زمینه صحیح فراخوانی شده است. آنچه React در اینجا انجام می دهد این است که عملکرد شما را در زمینه مناسب برای بروزرسانی حالت React فراخوانی کند. این مورد همچنین می تواند در موقعیت های دیگر استفاده از مقدار فعلی مفید باشد ، React تابع شما را با اولین آرگومان به عنوان مقدار فعلی فراخوانی می کند.
توجه داشته باشید: برای مطالعه بیشتر در مورد موضوع async و بسته شدن ، توصیه می کنم بخوانید “useState
تنبل راه اندازی اولیه و به روز رسانی عملکرد”توسط Kent C. Dodds.
توابع خطی JSX
در اینجا یک نسخه ی نمایشی Codepen از عملکرد داخلی JSX آمده است:
قلم را ببینید [Hello World in React](https://codepen.io/smashingmag/pen/QWgQQKR) توسط گوراو خانابه
دقیقاً یک API React به ازای هر گفتن نیست.
JSX از توابع درون خطی پشتیبانی می کند و می تواند برای اعلام منطق ساده با متغیرهای درون خطی مفید باشد ، به شرطی که یک عنصر JSX را برمی گرداند.
در اینجا مثالی آورده شده است:
function App() {
return (
<>
{(() => {
const darkMode = isDarkMode()
if (darkMode) {
return (
<div className="dark-mode"></div>
)
} else {
return (
<div className="light-mode"></div>
) // we can declare JSX anywhere!
}
})()} // don't forget to call the function!
</>
)
}
در اینجا ما کد داخل JSX را اعلام می کنیم ، می توانیم کد دلخواه را اجرا کنیم و تنها کاری که باید انجام دهیم این است که یک تابع JSX را برگرداند تا ارائه شود.
ما می توانیم آن را مشروط کنیم یا به سادگی منطقی را انجام دهیم. به پرانتزهای اطراف عملکرد درون خط توجه کنید. همچنین به خصوص در جایی که ما این تابع را فرا می خوانیم ، حتی اگر بخواهیم می توانیم یک استدلال را از زمینه اطراف به این تابع منتقل کنیم!
})()}
این می تواند در شرایطی مفید باشد که می خواهید ساختار داده ها را به صورت پیچیده تری نسبت به استاندارد عمل کنید .map
اجازه می دهد تا در داخل یک عنصر JSX.
function App() {
return (
<>
{(() => {
let str=""
for (let i = 0; i < 10; i++) {
str += i
}
return (<p>{str}</p>)
})()}
</>
)
}
در اینجا می توانیم تعدادی کد را برای حلقه مجموعه ای از اعداد اجرا کرده و سپس آنها را بصورت خطی نمایش دهیم. اگر از یک تولید کننده سایت استاتیک مانند گتسبی استفاده می کنید ، این مرحله نیز از قبل محاسبه می شود.
component extends type
این ویژگی برای ایجاد اجزای سازگار با تکمیل خودکار بسیار مفید است ، این امکان را به شما می دهد تا اجزایی را بسازید که موجود را گسترش می دهند HTMLElements
یا اجزای دیگر بیشتر برای تایپ صحیح یک رابط عناصر در Typescript مفید است ، اما برنامه اصلی برای JavaScript یکسان است.
در اینجا یک مثال ساده وجود دارد ، فرض کنید می خواهیم یک یا دو ویژگی a را نادیده بگیریم button
عنصر ، اما هنوز به توسعه دهندگان این امکان را می دهد که ویژگی های دیگر را به دکمه اضافه کنند. مانند تنظیم type="button"
یا type="submit"
به بدیهی است که ما نمی خواهیم کل عنصر دکمه را بازسازی کنیم ، ما فقط می خواهیم خواص موجود آن را گسترش دهیم ، و شاید یک قسمت دیگر نیز اضافه کنیم.
import React, { ButtonHTMLAttributes } from 'react'
ابتدا React و the را وارد می کنیم ButtonHTMLAttributes
class ، نوعی که شامل props a می شود HTMLButtonElement
به می توانید کد منبع این نوع رابط را در اینجا بخوانید:
و می بینید که تیم React همه API های وب را در TypeScript مجدداً پیاده سازی کرده است ، بنابراین می توان نوع آنها را بررسی کرد.
بعد ، ما رابط کاربری خود را به این صورت اعلام می کنیم ، و رابط کاربری خود را اضافه می کنیم status
ویژگی.
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
status?: 'primary' | 'info' | 'danger'
}
و در نهایت ، ما چند کار را انجام می دهیم. ما از تخریب ES6 برای بیرون کشیدن لوازم مورد نیاز خود استفاده می کنیم (status
، و children
) ، و هرگونه ویژگی دیگر را به عنوان اعلام کنید rest
به و در خروجی JSX ما ، یک عنصر دکمه را برمی گردانیم ، با ساختار ES6 برای افزودن هرگونه ویژگی اضافی به این عنصر.
function Button(props: ButtonProps) {
const { status, children, ...rest } = props // rest has any other props
return (
<button
className={`${status}`}
{...rest} // we pass the rest of the props back into the element
>
{children}
</button>
)
}
بنابراین در حال حاضر یک توسعه دهنده می تواند a را اضافه کند type
تکیه گاه یا هر وسیله دیگری که معمولاً یک دکمه دارد. ما یک ابزار اضافی ارائه داده ایم که در آن استفاده کرده ایم className
برای تنظیم سبک دکمه
در اینجا کل مثال است:
import React, { ButtonHTMLAttributes } from 'react'
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
status?: 'primary' | 'info' | 'danger'
}
export default function Button(props: ButtonProps) {
const { status, children, ...rest } = props
return (
<button
className={`${status}`}
{...rest}
>
{children}
</button>
)
}
این راهی عالی برای ایجاد اجزای داخلی قابل استفاده مجدد است که مطابق با دستورالعمل های سبک شما بدون بازسازی کل عناصر HTML است! به سادگی می توانید کل لوازم جانبی مانند تنظیم className
بر اساس وضعیت یا اجازه دهید نام کلاسهای اضافی نیز ارسال شود.
import React, { ButtonHTMLAttributes } from 'react'
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
status?: 'primary' | 'info' | 'danger'
}
export default function Button(props: ButtonProps) {
const { status, children, className, ...rest } = props
return (
<button
className={`${status || ''} ${className || ''}`}
{...rest}
>
{children}
</button>
)
}
در اینجا ما لوازم جانبی را می گیریم className
به عنصر دکمه ما منتقل می شود ، و آن را با یک بررسی ایمنی در مورد پایه ، دوباره وارد کنید undefined
به
نتیجه
React یک کتابخانه بسیار قدرتمند است و دلیل خوبی برای محبوبیت سریع آن وجود دارد. این یک ابزار عالی برای ساختن برنامه های وب کارآمد و آسان برای نگهداری به شما می دهد. این بسیار انعطاف پذیر و در عین حال بسیار سخت است ، که اگر بدانید چگونه از آن استفاده کنید می تواند فوق العاده مفید باشد. اینها تنها چند API هستند که قابل توجه هستند و تا حد زیادی نادیده گرفته می شوند. در پروژه بعدی خود آنها را امتحان کنید!
برای مطالعه بیشتر در مورد آخرین API های React ، قلاب ها ، خواندن را توصیه می کنم useHooks (🐠)به این Cheatsheet تایپیک همچنین اطلاعات بسیار خوبی برای React و Typescript Hooks دارد.
