لاعب جديد يدخل على الساحة بطريقة لعب اجمع جميع الخبراء على انها اسهل ما وجد برعاية من العملاق facebook
نعم انها مكتبة Recoiljs مكتبة لادارة الحالة ببساطة تتبنى مفهوم react لانها من تطوير فريقها ، نعم قالو انها ليست رسمية لكنها تحت غطائهم
هيا مصممة خصيصا للـ react ليس مثلها مثل Redux و mobx ليس عليك تعلم عديد المبادئ ;و المصطلحات وطرق العمل المعقدة ومحاولة فهم اشياء خارج مفهوم react
قبل ان نبدا افترض انك تعاملت مع React hooks
تعال نتفق على ان نتفق على انه معضم مكتبات ادارة الـ state تحاول جعلها global بحيث يمكن الوصول اليها من اي component و هذا الامر ليس مقتصر على React فقط بل معضم الاطر في الساحة
لابد وانك استعملت useState لتعيين state value للـ component الخاص بك وكما يعلمون ونعلم انه يمكنك الوصول لتلك value من اي مكان في الـ component
حسنا ما رايك ان اخبرك ان Recoil هو نفس useState لكن بامكانية انك يمكنك الوصول لل value و التعديل عليها من اي مكان في تطبيقك
نعم الامر بهذه البساطة حبيبي في الله تاتي مكتبة Recoil بمفهومين اساسين لا غير هما atoms و selectors
ولنفهم هذه المفاهيم سنقوم ببناء تطبيقنا الاول بها
اولا لابد من انشاء مشروع react جديد
و الان لنقم باضافة Recoil.js لمشروعنا
عبر npm
npm install recoil
او عبر Yarn
yarn add recoil
و الان لنقم بافراغ ملف App.js
ونجعله بهذا الشكل
import React from 'react';
import "./App.css"
const App = () => {
return (
<div className="App" >
<h1> Coretabes </h1>
</div>
);
}
export default App;
و الان دخول الاعب الجديد للميدان
اول شيء نقوم به هو استدعاء الـ RecoilRoot
ونقوم باستخدامه بهذا الشكل
import React from 'react';
import "./App.css"
// New
import { RecoilRoot } from 'recoil';
const App = () => {
return (
<RecoilRoot>
<div className="App" >
<h1> Coretabes </h1>
</div>
</RecoilRoot>
);
}
export default App;
ولتوضح ما قمنا به ، قمنا باستدعاء component الـ RecoilRoot
وهو المكون الذي سنغلف يه اعلى مكون لدينا الذي سيتيح لنا الوصول للـ state من اي مكان في تطبيقنا
والان لنقم بانشاء component الذي هو عبارة عن عداد بسيط اسمه Counter
ولنقم باضافته في App.js
import React from 'react';
import "./App.css"
import { RecoilRoot } from 'recoil';
// New
const Counter = () => {
return <button>0</button>
}
const App = () => {
return (
<RecoilRoot>
<div className="App" >
<Counter/>
</div>
</RecoilRoot>
);
}
export default App;
و الان لنقم بانشاء اول atom
لنا وثم سنشرحه
import React from 'react';
import "./App.css"
// New
import { RecoilRoot, atom } from 'recoil';
// New
const numStateValue = atom({
key: 'numStateValue',
default : 0
})
const Counter = () => {
return <button>0</button>
}
const App = () => {
return (
<RecoilRoot>
<div className="App" >
<Counter/>
</div>
</RecoilRoot>
);
}
export default App;
وللتركيز على الامر هذه هيا طريقة كتابة atom
// (recoil) من (atom) نقوم باستراد دالة
import { RecoilRoot, atom } from 'recoil';
// (object) التي تستقبل (atom) متغير الحالة يحتوى على دالة
const numStateValue = atom({
key: 'numStateValue',
default : 0
})
ومنه atom هيا دالة تنشئ لنا state value تستقبل object يجب ان يحتوي اول قيمة key المهم ان تكون القيمة قريدة unique لانها تساعد في تتبع الاخطاء و القيمة default وهي القيمة الافتراضية
وهكذا يصبح لدنا state value ( numStateValue
) يمكننا مشاركتها لاي components وهيا قابلة للتحديث وعند تحديثها تتغير في جميع الـ components التي قمنا بمشاركتها فيها و الان لنقم بمشاركتها في اول component لنا وهو Counter
// (useٍState) وهي ستعوض (useRecoilState) نقوم باستيراد
import { RecoilRoot, atom, useRecoilState } from 'recoil';
// (useRecoilState) باستخدام (state variable) ونقوم بانشاء
const Counter = () => {
const [number, setNumber] = useRecoilState(numStateValue)
return (
<button onClick={() => setNumber(number + 1)}>
{number}
</button>)
}
كما تلاحظ قنا بمشاركة atom الخاص بنا numStateValue
الى useRecoilState كقيمة للstate الخاص بالـ component counter وقمنا ايضا انشاء حدث وهو عند النقر على button
يقوم بزيادة 1 للقيمة السابقة .
وهكذا يمكنك مشاركة
numStatevalue
لاي مكون في تطبيقك باستعمالuseRecoilState
للقرائة و التعديل بكل بساطة
ولكن ماذا لو اردنا فقط عرض قيمة numStatevalue
وفي مكون اخر يعني انه سننشئ مكون اخر يقوم بعرض لنا قيمة العداد الخاص بنا
...
...
...
// New
const DisplayCounter = () => {
const [number, setNumber] = useRecoilState(numStateValue)
return <h1>{number}</h1>
}
const App = () => {
return (
<RecoilRoot>
<div className="App" >
<Counter />
<DisplayCounter />
</div>
</RecoilRoot>
);
}
export default App;
لقد قمنا بانشاء component جديد DisplayCounter
و قمنا باضافته للـ App
وقمنا بتعيين state variable باستخدام useRecoilState وقمنا بتعيين قيمتها بـ numStateValue
لنحصل على هذه النتيجة بمجرد تحديث قيمة العداد تتحدث قيمة DisplayCounter
كما ترى قمنا بمشاركة atom (numStateValue)
الخاص بنا بين مكوانتنا لكن ان ركزنا في في الكود فهو يعمل بشكل عادي لكنه ليس عملي
كيف ليس عملي ؟
في الـ component الاول Counter
كنا نحتاج للتعديل وقرائة قيمة الـ atom الخاص بنا
و في الـcomponent الثاني DisplayCounter
لم نكن نحتاج للتعديل بل احتجنا فقط لقيمة state
اذا الحل بسيط نقوم باستعمال خطاف useRecoilValue
نقوم باستيراده من recoil
ببساطة يسمح لنا useRecoilValue
بقرائة قيمة state value فقط هكذا
import { RecoilRoot, atom, useRecoilState, useRecoilValue } from 'recoil';
const DisplayCounter = () => {
// const [number, setNumber] = useRecoilState(numStateValue)
const number = useRecoilValue(numStateValue)
return <h1>{number}</h1>
}
وهكذا اصبح كودنا نضيف وعملي اكثر وحصلنا على نفس النتيجة وهذا الكود الخاص بنا كاملا
import React from 'react';
import "./App.css"
import { RecoilRoot, atom, useRecoilState, useRecoilValue } from 'recoil';
const numStateValue = atom({
key: 'numStateValue',
default: 0
})
const Counter = () => {
const [number, setNumber] = useRecoilState(numStateValue)
return (<button onClick={() => setNumber(number + 1)}>{number}</button>)
}
const DisplayCounter = () => {
const number = useRecoilValue(numStateValue)
return <h1>{number}</h1>
}
const App = () => {
return (
<RecoilRoot>
<div className="App" >
<Counter />
<DisplayCounter />
</div>
</RecoilRoot>
);
}
export default App;
وهكذا نكون تعرفنا على atoms وطريقة مشاكرتها بين components نظريا وتطبيقيا
و الان لنتعرف المفهوم الثاني معنا في هذه المكتبة نعم انها Selectors
لو اردنا انشاء قيمة تعتمد على state value السابقة و قابلة للتحديث بمجرد تحديث الـ state value بمفهوم اخر تستند في قيمتها على state value
هنا ياتي دور selectors ولنفهمها اكثر سنقوم بالتعامل معها في تطبيقنا البسيط
نريد ان يتم ضرب القيمة الحالية لل atom numStateValue
في 2 وكل مرة تتغير القيمة يقوم selector بتحديث نفسه
ال selector يتعامل مع atom او selectors اخر و الان ناتي للتطبيق
import { RecoilRoot, atom, useRecoilState, useRecoilValue, selector } from 'recoil';
const multiplicationNumber = selector({
key: 'multiplicationNumber',
get: ({get}) => {
return get(numStateValue) * 2;
}
})
الـ selector يستقبل object يحتوي على key ويجب ان يكون فريد unique لا يكون مستخدم من قبل اي selector or atom و القيمة الثانية هيا get و تكون دالة تستقبل خاصية get تقوم بجلب اي selector او atom كما تلاحظ قمنا بجلب atom الخاص بنا numStateValue
وقمنا بضربه في 2 و الان بقي امر واحد لنقوم به وهو عرض نتيجة هذا selector
const DisplayCounter = () => {
const number = useRecoilValue(numStateValue)
// New
const multiplication = useRecoilValue(multiplicationNumber)
return (
<div>
<h1>{number}</h1>
<h1>Multiplication Number : {multiplication}</h1>
</div>
)
}
لقد قمنا بالتعديل على الـ component DisplayCounter
وقمنا بعرض قيمة الـ selector multiplicationNumber
بكل بساطة باستخدام useRecoilValue
التي قلنا انها للقرائة فقط
ويمكنك مشاركة الـ selector في اي components في تطبيقك مثله مثل atom
وستكون هذه هيا النتيجة النهائية لتطبيقنا
وهذا الكود النهائي لتطبيقنا
import React from 'react';
import "./App.css"
import { RecoilRoot, atom, useRecoilState, useRecoilValue, selector } from 'recoil';
const numStateValue = atom({
key: 'numStateValue',
default: 0
})
const multiplicationNumber = selector({
key: 'multiplicationNumber',
get: ({get}) => {
return get(numStateValue) * 2;
}
})
const Counter = () => {
const [number, setNumber] = useRecoilState(numStateValue)
return (<button onClick={() => setNumber(number + 1)}>{number}</button>)
}
const DisplayCounter = () => {
const number = useRecoilValue(numStateValue)
const multiplication = useRecoilValue(multiplicationNumber)
return (
<div>
<h1>{number}</h1>
<h1>Multiplication Number : {multiplication}</h1>
</div>
)
}
const App = () => {
return (
<RecoilRoot>
<div className="App" >
<Counter />
<DisplayCounter />
</div>
</RecoilRoot>
);
}
export default App;
اذا اردت تجربته لايف و التعديل عليه هذا الرابط
اضـغـط هـــــــــنا
الامر بسيط فقط افتح محررك
استودعكم الله
المصادر :