כיצד ליצור פרויקט Rails עם חזית React ו- Redux

מדריך מלא להגדרת אפליקציית Javascript עם עמוד יחיד עם React ו- Redux בתוך פרויקט Rails.

עדכון (17 במרץ, 2019): הוסף טיפוסי כתב לשלב האחרון של פרויקט זה.

מדריך זה יראה לכם כיצד ליצור אפליקציה עם עמוד יחיד עם React (ו- Redux ו- Semantic UI) בתוך פרויקט Rails.

מדריך זה יכלול גם:

  • Redux
  • תגובת נתב
  • בחר מחדש
  • Redux Think
  • ממשק משתמש סמנטי

הערת צד 1. ראיתי את המדריך הנפלא הזה לאחרונה וזה נתן לי השראה לכתוב אחד עבור Rails.

הערת צד 2. הנה המדריך המוגמר. היסטוריית ההתחייבות תואמת (סוג של) עם השלבים במדריך זה.

סקירה כללית

כדי לתת לך תחושה של מה אנחנו הולכים לבנות ואיך הדברים יעבדו, עיין ב -2 התרשימים שלמטה.

תרשים 1: טיפול בבקשת ה- HTTP הראשונה (כלומר בקשות מהדפדפן לאפליקציית Rails שלנו)

התרשים שלהלן ממחיש את אפליקציית React שלך בתוך פרויקט Rails שלך ואת הנתיב (קו שחור מלא) שעושה הבקשה הראשונה להחזרת יישום React ללקוח (דפדפן).

תרשים 2: טיפול בבקשות HTTP עוקבות (כלומר בקשות מאפליקציית React לאפליקציית Rails)

לאחר טעינת אפליקציית React בדפדפן המשתמש, אפליקציית React תהיה אחראית למשלוח בקשות לאפליקציית Rails שלך (קו שחור מלא). במילים אחרות, ברגע שנטען React, בקשות ל- Rails יגיעו מקוד Javascript, ולא מהדפדפן.

הערות חשובות אחרות לפני שנתחיל בקידוד

  • חשוב על אפליקציית React שלך שהיא נפרדת מאפליקציית Rails שלך. אפליקציית React מיועדת לממשק הקצה בלבד ופועלת בדפדפן המשתמש. החלק Rails הוא אך ורק עבור ה- back-end ופועל בשרת. אפליקציית Rails אינה יודעת דבר על אפליקציית React למעט מתי להחזיר את הנכסים הסטטיים שלה (Webpack הידור HTML, JS ו- CSS).
  • לאחר טעינת אפליקציית React שלך על ידי הדפדפן שלך, כל ההיגיון לביצוע בקשות HTTP (אחזור נתונים והפיכת הנתונים לתצוגה) מתבצע בחזית (כלומר הדפדפן).
  • אפליקציית Rails שלך למעשה אינה מציגה שום תצוגה פרט לזו שמשרתת את אפליקציית React שלך. במדריך זה, תצוגת Rails היחידה היא/app/views/static/index.html.erb
  • כל /api/*הנתיבים מטופלים על ידי אפליקציית Rails, בעוד שכל הנתיבים האחרים מטופלים על ידי React בתוך הדפדפן (לאחר שהדפדפן שלך טען את הבקשה הראשונה). לדוגמא, //your-app.com/somethingיישלח לאפליקציית Rails, ואז יחזור לאפליקציית React שלך (ה- HTML / JS / CSS שכבר נטען בדפדפן), שתחליט מה להציג על המסך.
  • שיקולים לבניית אפליקציה בעמוד יחיד. לא הכרחי להדרכה זו אך שימושי.
  • תגובה דפוסי עיצוב רכיבים. שוב, לא הכרחי אבל שימושי.

דרישות מערכת

לידיעתך הנה תצורת המערכת שלי. לא אומר שאתה צריך את זה, אבל משהו דומה יהפוך את חוויית ההדרכה הזו לחלקה יותר.

  • macOS 10.13.6 (High Sierra)
  • רובי 2.5.1
  • מסילות 5.2.1 (ובונדלר 1.16.6)
  • - חבילה להתקנת פנינה - v 1.16.6
  • צומת 9.8.0

לבסוף, על הקוד!

שלב 1: צור פרויקט Rails חדש באמצעות Webpack ו- React

צור אפליקציית Rails חדשה. קראתי את שלי rails-react-tutorial.

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

ראה כאן למידע נוסף על --webpack=reactהדגל שהוצג במסילות 5.1.

שלב 2: ודא כי אבני החן של Webpacker ו- React-Rails מותקנות

בדוק אם אבני החן של 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: הוסף מחלקת בקר ונתיב לאפליקציית Rails שלנו

הוסף מסלול חדש לאפליקציית Rails שלנו. לדוגמא זו נוסיף GET /v1/thingsנקודת קצה ל- config/routes.rb`.

מסלול חדש זה ידרוש ThingsController. צור app/controllers/v1/things_controller.rbקובץ חדש . זכור, זה אמור להיות v1בתיקיה מכיוון שהיא שייכת ל- Rails API שלנו.

בקר הדברים שלנו יחזיר תגובה מקודדת קשה GET /v1/things.

בשלב זה, אתה אמור להיות מסוגל לרוץ מחדש rails server -p 3000ולבקר //localhost:3000/v1/things.

לאחר מכן, ניצור רכיב React חדש.

שלב 4: צור רכיב React חדש

צור רכיב HelloWorld React המקבל פרמטר מחרוזת בשם על 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 ייארזו אוטומטית באמצעות webpack).

כעת, כשיש לנו רכיב React שעובד בעינינו, בואו נרחיב את האפליקציה שלנו כך שתתמוך במספר תצוגות react-router.

שלב 6: הוסף נתב תגובה

ראשית, הפעל פקודה זו להוספה react-router-dom, הכוללת ומייצאת את כל react-routerרכיבי העזר הנוספים וחלקם נוספים לגלישה באינטרנט. מידע נוסף כאן.

npm install --save react-router-domyarn install

פקודה זו אמורה להוסיף את השורה הבאה package.jsonלקובץ שלך . הערה, 4.2.2 שימש כאן, אך הגרסה שלך יכולה להיות שונה.

עכשיו בואו נשתמש בנתב תגובה כדי ליצור כמה מסלולים עבור חזית התגובה שלנו.

שלב 6: שימוש בנתב תגובה

react-routerמאפשר לנו לנהל את כל מסלולי ממשק המשתמש שלנו אך ורק באמצעות Javascript. המשמעות היא שנצטרך רכיב "אפליקציה" יחיד שמקיף את כל היישום שלנו. "App" ישתמש גם ב- React-Router כדי להציג את רכיב ה- "עמוד" הנכון עבור כתובת ה- URL המתבקשת.

כדי להתחיל, הפעל פקודה זו כדי להוסיף רכיב אפליקציה שייצג את כל היישום החזיתי שלנו.

rails generate react:component App

לאחר מכן, פתח את הקובץ עבור רכיב React החדש שנוצר, app/javascript/components/App.jsוהוסף את הדברים הבאים ...

עכשיו שנה index.html.erbכדי להצביע על רכיב האפליקציה החדש שלנו.

לבסוף, ערוך את ש- routes.rbRails ישלח לך את כל הבקשות שאינן לממשק ה- API לרכיב האפליקציה שלנו (דרך StaticController#index).

כעת אנו יכולים להפעיל rails server -p 3000וביקור //localhost/ו //localhost/helloלראות לת-נתב עובד (זוכרים ./bin/webpack-dev-serverמאפשר-webpacking אוטומטי).

בשלב הבא נצטרך להתקין כמה תלות נוספות לפני שנוכל לחבר את ממשק ה- React שלנו ל- API של Rails.

שלב 7: הוספת Redux, Sagas, Babel Polyfill ו- Axios

עכשיו בואו נוסיף את ספריות Javascript הבאות לחזית הקצה שלנו.

  • Redux לניהול המצב העולמי של היישום שלנו.
  • Babel-Polyfill כדי לאפשר תכונות Javascript מהודרות שאולי לא יהיו זמינות בדפדפני אינטרנט ישנים יותר.
  • בחר מחדש והגדר את Redux כדי להקל על העבודה עם Redux.

כדי להתקין הכל, הפעל את הפעולות הבאות:

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

כעת נשתמש בכלים אלה להקמת חנות מדינת Redux, ולאחר מכן נוסיף כמה פעולות ומפחיתים לשימוש בה.

שלב 8: הגדר את Redux State Store

בשלב זה, נגדיר את חנות Redux State עבור האפליקציה שלנו עם התבנית הבאה (נוסיף ונסיר "דברים" בשלבים הבאים).

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

ראשית, צור configureStore.jsקובץ. זה יאתחל את חנות Redux שלנו.

כעת ייבא והשתמש configureStore()ברכיב האפליקציה כדי ליצור מצב Redux ולחבר אותו לאפליקציה שלנו.

עכשיו התקנתם את Redux באפליקציה שלכם! לאחר מכן, ניצור פעולה וצמצום, ונתחיל לכתוב ולקרוא ממדינת הרדוקס שלנו.

שלב 9: הוסף פעולה ומפחית

כעת, כאשר לאפליקציה יש מדינת Redux, נוסיף a 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!