كيفية إنشاء مشروع ريلز بواجهة أمامية لـ React و Redux

دليل كامل لإعداد تطبيق Javascript من صفحة واحدة باستخدام React و Redux داخل مشروع Rails.

تحديث (17 مارس 2019): تمت إضافة كتابة نصية إلى الخطوة الأخيرة من هذا المشروع.

سيوضح لك هذا البرنامج التعليمي كيفية إنشاء تطبيق من صفحة واحدة باستخدام React (و Redux و Semantic UI) داخل مشروع Rails.

سيتضمن هذا البرنامج التعليمي أيضًا:

  • إعادة
  • رد فعل راوتر
  • إعادة تحديد
  • أعد التفكير
  • واجهة المستخدم الدلالية

ملاحظة جانبية رقم 1. لقد رأيت هذا الدليل الرائع مؤخرًا وقد ألهمني لكتابة واحد لـ Rails.

ملاحظة جانبية # 2. هنا هو البرنامج التعليمي النهائي. يتوافق تاريخ الالتزام (نوعًا ما) مع الخطوات الواردة في هذا الدليل.

نظرة عامة

لتعطيك فكرة عما سنبنيه وكيف ستعمل الأشياء ، انظر المخططين أدناه.

الرسم التخطيطي 1: معالجة طلب HTTP الأول (أي الطلبات من المتصفح إلى تطبيق ريلز الخاص بنا)

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

الرسم التخطيطي 2: معالجة طلبات HTTP اللاحقة (أي الطلبات من تطبيق React الخاص بنا إلى تطبيق Rails الخاص بنا)

بعد تحميل تطبيق React في متصفح المستخدم ، سيكون تطبيق React مسؤولاً عن إرسال الطلبات إلى تطبيق Rails الخاص بك (الخط الأسود الثابت). بعبارة أخرى ، بمجرد تحميل React ، ستأتي الطلبات إلى ريلز من كود جافا سكريبت وليس من المتصفح.

ملاحظات مهمة أخرى قبل أن نبدأ في الترميز

  • فكر في تطبيق React على أنه منفصل عن تطبيق ريلز الخاص بك. تطبيق React مخصص تمامًا للواجهة الأمامية ويتم تشغيله في متصفح المستخدم. جزء ريلز مخصص بشكل صارم للجهة الخلفية ويعمل على الخادم. لا يعرف تطبيق ريلز أي شيء عن تطبيق React باستثناء وقت إرجاع أصوله الثابتة (Webpack المترجمة HTML و JS و CSS).
  • بمجرد أن يتم تحميل تطبيق React الخاص بك بواسطة متصفحك ، يتم تنفيذ كل المنطق لعمل طلبات HTTP (استرداد البيانات وتحويل تلك البيانات إلى عرض) في الواجهة الأمامية (أي المتصفح).
  • لا يقدم تطبيق ريلز الخاص بك بشكل فعال أي طرق عرض باستثناء تلك التي تخدم تطبيق React الخاص بك. في هذا البرنامج التعليمي ، طريقة عرض ريلز الوحيدة هي/app/views/static/index.html.erb
  • /api/*يتم التعامل مع جميع المسارات بواسطة تطبيق ريلز ، بينما يتم التعامل مع جميع المسارات الأخرى بواسطة React داخل المتصفح (بعد أن يقوم متصفحك بتحميل الطلب الأول). على سبيل المثال ، //your-app.com/somethingسيتم إرسالها إلى تطبيق ريلز ، ثم إعادتها مرة أخرى إلى تطبيق React (HTML / JS / CSS الذي تم تحميله بالفعل في المتصفح) ، والذي سيقرر ما سيتم عرضه على الشاشة.
  • اعتبارات لبناء تطبيق من صفحة واحدة. ليس ضروريًا لهذا البرنامج التعليمي ولكنه مفيد.
  • تفاعل أنماط تصميم المكونات. مرة أخرى ، ليست ضرورية ولكنها مفيدة.

متطلبات النظام

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

  • macOS 10.13.6 (هاي سييرا)
  • روبي 2.5.1
  • ريلز 5.2.1 (والحزمة 1.16.6)
  • - حزمة تثبيت الأحجار الكريمة -v 1.16.6
  • العقدة 9.8.0

أخيرًا ، إلى الكود!

الخطوة 1: أنشئ مشروع ريلز جديدًا باستخدام Webpack و React

أنشئ تطبيق ريلز جديدًا. لقد سميت لي rails-react-tutorial.

rails new rails-react-tutorial --webpack=react

انظر هنا لمزيد من المعلومات حول --webpack=reactالعلم المقدم في الإصدار 5.1 من ريلز.

الخطوة 2: تأكد من تثبيت Webpacker و React-Rails gems

تحقق مما إذا كانت جواهر Webpacker و React -Rails موجودة في ملف Gemfile. إذا لم تكن الأحجار الكريمة موجودة ، فأضفها:

الآن قم بتشغيل هذه الأوامر لتثبيت كل شيء.

bundle install
# This command might not be necessary.# If already installed, then it will# ask you to override some files.rails webpacker:install
rails webpacker:install:react rails generate react:installyarn install 

الآن قم بتشغيل rails server -p 3000 وزيارة //localhost:3000للتأكد من أن مشروعنا يعمل.

نصيحة للمحترفين رقم 1 : قم بالتشغيل ./bin/webpack-dev-serverفي نافذة منفصلة أثناء الترميز لإجراء أي تغييرات تقوم تلقائيًا ببناء المتصفح وإعادة تحميله.

نصيحة للمحترفين رقم 2 : إذا تلقيت هذا الخطأ can’t activate sqlite3 (~> 1.3.6), already activated sqlite3–1.4.0 ، فسيكون dd gem ‘sqlite3’, ‘~>1.3.6 'إلى Gemfile. انظر هذا الرابط لمزيد من المعلومات.

الخطوة 3: أضف فئة تحكم ، وطريق ، إلى تطبيق ريلز الخاص بنا

أضف مسارًا جديدًا إلى تطبيق ريلز الخاص بنا. في هذا المثال ، سنضيف GET /v1/thingsنقطة نهاية إلى ملف config/routes.rb.

سيتطلب هذا المسار الجديد عنصر تحكم ThingsController. قم بإنشاء app/controllers/v1/things_controller.rbملف جديد . تذكر أنه يجب أن يكون في v1المجلد لأنه ينتمي إلى واجهة برمجة تطبيقات Rails الخاصة بنا.

ستعيد وحدة التحكم في الأشياء الخاصة بنا استجابة مشفرة لـ GET /v1/things.

في هذه المرحلة ، يجب أن تكون قادرًا على إعادة التشغيل rails server -p 3000والزيارة //localhost:3000/v1/things.

بعد ذلك ، سننشئ مكون React جديدًا.

الخطوة 4: إنشاء مكون React جديد

قم بإنشاء مكون HelloWorld React الذي يقبل معلمة String تسمى greetingعن طريق تشغيل الأمر التالي:

rails generate react:component HelloWorld greeting:string

يجب إنشاء ملف: app/javascript/components/HelloWorld.js.

الخطوة 5: استخدم مكون HelloWorld الخاص بنا

لاستخدام مكون HelloWorld الجديد الخاص بنا ومشاهدته ، نحتاج إلى شيئين: إنشاء طريقة عرض تتضمن هذا المكون ، وإضافة مسار للإشارة إلى وجهة النظر هذه.

لإنشاء عرض ، قم بإنشاء الملف app/views/static/index.html.erbوأضف ما يلي:

routes.rbلمسارنا الجديد ، أضف السطر التالي إلى ملفنا ، و StaticController فارغًا لدعمه.

أضف هذا إلى app/controllers/static_controller.rb:

يجب أن تكون الآن قادرًا على إعادة التشغيل rails server -p 3000والزيارة //localhost:3000/لرؤية مكون React الجديد الخاص بك (تذكر أن تعمل ./bin/webpack-dev-serverفي نافذة منفصلة لكي يتم تجميع تغييرات Javascript تلقائيًا بواسطة حزمة الويب).

الآن بعد أن أصبح لدينا مكون React الذي يتم عرضه في رأينا ، دعنا نوسع تطبيقنا لدعم طرق عرض متعددة به react-router.

الخطوة 6: أضف React-Router

أولاً ، قم بتشغيل هذا الأمر للإضافة react-router-dom، والذي يتضمن ويصدر كل react-routerوبعض مكونات المساعد الإضافية لتصفح الويب. مزيد من المعلومات هنا.

npm install --save react-router-domyarn install

يجب أن يضيف هذا الأمر السطر التالي إلى ملفك package.json. لاحظ أنه تم استخدام 4.2.2 هنا ، لكن إصدارك قد يكون مختلفًا.

لنستخدم الآن جهاز React Router لعمل بعض المسارات للواجهة الأمامية لـ React.

الخطوة 6: استخدام React-Router

react-routerيسمح لنا بإدارة جميع مسارات واجهة المستخدم الخاصة بنا بدقة باستخدام جافا سكريبت. هذا يعني أننا سنحتاج إلى مكون "تطبيق" واحد يغلف تطبيقنا بالكامل. سيستخدم "التطبيق" أيضًا React-Router لتقديم مكون "الصفحة" الصحيح لعنوان URL المطلوب.

للبدء ، قم بتشغيل هذا الأمر لإضافة مكون التطبيق الذي سيمثل تطبيق الواجهة الأمامية بالكامل.

rails generate react:component App

بعد ذلك ، افتح الملف لمكون React الذي تم إنشاؤه حديثًا app/javascript/components/App.js، وأضف ما يلي ...

غيّر الآن index.html.erbللإشارة إلى مكون التطبيق الجديد.

أخيرًا ، قم بتحرير الخاص بك routes.rbليقوم ريلز بإرسال جميع الطلبات غير المخصصة لواجهة برمجة التطبيقات إلى مكون التطبيق لدينا (عبر StaticController#index).

يمكننا الآن تشغيل rails server -p 3000وزيارة //localhost/و //localhost/helloلمعرفة رد فعل جهاز توجيه العمل (تذكر ./bin/webpack-dev-serverيمكن لصناعة السيارات في webpacking).

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

الخطوة 7: إضافة Redux و Sagas و Babel Polyfill و Axios

لنقم الآن بإضافة مكتبات جافا سكريبت التالية لواجهتنا الأمامية.

  • Redux لإدارة الحالة العالمية لتطبيقنا.
  • Babel-Polyfill لتمكين ميزات Javascript الرائعة التي قد لا تكون متاحة بخلاف ذلك على متصفحات الويب القديمة.
  • أعد التحديد و React-Redux لتسهيل العمل مع Redux.

لتثبيت كل شيء ، قم بتشغيل ما يلي:

npm install --save redux babel-polyfill reselect react-reduxyarn install

سنستخدم الآن هذه الأدوات لإعداد Redux State Store ، ثم نضيف بعض الإجراءات والمخفضات لاستخدامه.

الخطوة 8: قم بإعداد Redux State Store

في هذه الخطوة ، سنقوم بإعداد Redux State Store لتطبيقنا بالقالب التالي (سنضيف "أشياء" ونزيلها في الخطوات التالية).

{ "things": [ { "name": "...", "guid": "..." } ]}

أولاً ، قم بإنشاء configureStore.jsملف. سيؤدي هذا إلى تهيئة متجر Redux الخاص بنا.

الآن قم بالاستيراد والاستخدام configureStore()في مكون التطبيق لإنشاء حالة Redux وربطها بتطبيقنا.

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

الخطوة 9: أضف إجراءً ومخفضًا

الآن بعد أن أصبح للتطبيق حالة إعادة التشغيل ، سنضيف ملف on> to HelloWorld that dispatches an Action (that we will define here) that will be received b y the rootReducer().

First, add getThings() Action definition and import createStructuredSelector() and connect() into theHelloWorld Component. This maps parts of the Redux State, and Actions (i.e. dispatching getThings()) , to HelloWorld’s prop.

Next, add a on> to HelloWorld that dispatc hes a getThings() Action (from ./actions/index.js) on every click.

After everything is added to HelloWorld, go to //localhost:3000/hello, open the Console, and click the “getThings” button to see your Action and Reducer functions being called.

Now that you can send an Action that can be received by a Reducer, let’s have the Reducer alter the Redux State.

Step 10: Have HelloWorld read React State and display “things”

Insert a List <ul> in HelloWorld and fill it with “things” from your Redux State.

To test if this is actually working, we can initialize with some “things” data. Once this is done, we can refresh the page and see it in our list.

Now that we have a simple Action and Reducer working, we will extend this so that the Action queries our Rails API and the Reducer sets the content of “things” with the API response.

Step 11: Install Redux-Thunk

We will need Redux-Thunk to allow async workflows (like an HTTP request) to dispatch Actions.

Install redux-thunk by running this command:

npm install --save redux-thunkyarn install

Now, let’s use Thunk in our Action!

Step 12: Use redux-thunk and fetch() to query API and set React State with results

First, let’s import redux-thunk in configureStore.js and install it our Redux Store so our App can handle “Thunk” Actions.

Now test that everything is working by starting the App and loading a page.

Next, let’s change the getThings() Action to return a function that performs the following (instead of returning the Action object):

  1. Dispatch the original Action object
  2. Make a call to our Rails API.
  3. Dispatch a new Action getThingsSuccess(json) when the call succeeds.

For this step, we will also need to add the getThingsSuccess(json) Action.

Of course, this does nothing to the Redux State since our Reducer is not making any changes. To fix this, change the Reducer to handle the GET_THINGS_SUCCESS Action and return the new State (with the response from the Rails API).

Now if you start your App, navigate to localhost:3000/hello and click the button, your list should change!

There you have it. A Rails API hooked up to a React+Redux App.

(Bonus) Step 13: Installing Redux Dev Tools

Maybe I should’ve put this step earlier, but Redux Dev Tools is essential for debugging the Actions your App is sending, and how those Actions are changing your State.

This is how you install it. First, install the proper extension for your browser (Chrome, Firefox).

Next, run the following to install the library.

npm install --save-dev redux-devtools-extensionyarn install

Now, use it to initialize your Redux State Store.

After all this is done, you should be able to see a new tab, Redux, in your Chrome (or Firefox) dev tools, that lets you see which Actions were dispatched, and how each one changed the App’s State. The React tab will also show you all your components and their props and states.

Happy debugging!

(Bonus) Step 14: Semantic UI

Semantic is a great library for UI components that makes it really easy to build nice looking websites quickly.

To install this library, run the following.

npm install --save semantic-ui-css semantic-ui-reactyarn install

Add this to app/javascript/packs/application.js:

import 'semantic-ui-css/semantic.min.css';

And add this to app/views/static/index.html.erb:

 'all' %

(Bonus) Step 15: Using a Reasonable Directory Structure

This step is totally optional, and it has nothing to do with the function of the App. Just my opinion on how you should organize your files.

So as you can probably guess, stuffing your Actions into the same file as your Components, and having a single reducer for your entire App, does not scale very nicely when your App grows. Here is my suggested file structure:

app|-- javascript |-- actions |-- index.js |-- things.js |-- components |-- packs |-- reducers |-- index.js |-- things.js

(Bonus — Mar 17 2019 Update) Step 16: Install Typescript!

Typescript is just like Javascript but with types! It is described as a “strict syntactical superset of Javascript”, meaning that Javascript is considered valid Typescript, and the “type features” are all optional.

IMO Typescript is fantastic for large Javscript projects, such as a big React front-end. Below are instructions on how to install it, and a small demo of it inside our project.

First, run the following commands (taken from the Webpacker Readme):

bundle exec rails webpacker:install:typescriptyarn add @types/react @types/react-dom

Now, to see it in action, let’s rename app/javascript/reducers/things.js to things.tsx and add the following lines to the top of the file:

After you add interface Thing , let’s use it by having const initialState use that type (seen in the screenshot above), and specify that thingsReducer return an array of type Thing (also seen in the screenshot).

Everything should still work, but to see Typescript in action, lets add a default case to thingsReducer and add return 1 . Since 1 is not a Thing type we will see the output of ./bin/webpack-dev-server fail with the following:

And that’s it! You can now add Typescript .tsx files to your project and start using Types with your project.

Here’s a great overview of Typescript and why you should use it.

The End

You made it! You’ve made a Rails App that uses React and Redux. That’s pretty much it for the tutorial. I hope you had fun and learned something along the way.

If you build something with React and Rails, please do share it in the comments below — along with any questions or comments you may have for me.

Thanks for reading!