# Job Router ## User flow 1. Khi ở `/` - Homepage.js ![](https://i.imgur.com/XhzsqEL.png) 2. Click button `Learn More` Nếu chưa login -> redirect tới trang `/form` - FormPage.js ![](https://i.imgur.com/SL980oB.png) Nếu đã login —> redirect tới trang `/job/:id` - JobPage.js ![](https://i.imgur.com/aYnfvfv.jpg) ## Code walkthrough ### `./page` Từ flow bên trên mình có nhận ra có 3 trang chính sau: 1. `/Homepage.js` - Homepage sẽ render SearchAppBar và JobList. Trong JobList render các components JobBox. ![](https://i.imgur.com/X9VydXF.png) ```javascript function JobPage() { return ( <div> <SearchAppBar/> <JobList/> </div> ) } ``` 2. `/FormPage.js` - FormPage sẽ render 1 component Form. ```javascript function JobPage() { return <Form/>; } ``` 3. `/JobPage.js` - JobPage là nơi cần được "protect". Bạn sẽ bọc `<RequireAuth>` ngoài `<JobPage>` ```javascript <Route path="job/:id" element={ <RequireAuth> <JobPage /> </RequireAuth> } /> ``` - JobPage render một Modal - chứa thông tin job detail. ```javascript function JobPage() { let { id } = useParams();//useParams to get the job id from your url. Please look this up in the doc const job = jobs.find((job) => job.id === id); return ( <Modal> //your code here </Modal> ) } ``` **Note:** Bạn có thể dùng [Modal MUI](https://mui.com/material-ui/react-modal/) này. ### `./components` 1. `/JobList.js` ```javascript function JobList() { return ( jobs.map(()=> <JobBox/>) ); } ``` 2. `/JobBox.js` ```javascript function JobBox() { const location = useLocation() return ( <div> <h1>Job Name</h1> <button component={?} to={?} state={?} >Learn More</button> </div> ); } ``` - Khi click vào button LearnMore bạn muốn di chuyển đến trang JobPage. ==> Button này là một Link, và lúc click button này mình muốn đi tới trang `/job/:id` (`to={}`), đồng thời lưu lại vị trí hiện tại để làm background cho trang này (`state={}`). - Vì sao cần location làm background cho trang `/job/:id`? ![](https://i.imgur.com/f75uNzM.jpg) Với UI này mình nghĩ là app render Modal ở trang `/`, nhưng thật ra là mình đã tới trang `/job/:id` và trang đó có background là `location` mà mình đã lưu khi click button. (effect Modal 😈😭) - Làm sao để lấy ra địa chỉ đó để lưu? useLocation()- dùng để lấy ra địa chỉ. [(doc)](https://reactrouter.com/docs/en/v6/hooks/use-location) 1. `/Form.js` - Component Form này render 1 Modal. Modal này chứa 1 form được build bằng react-hook-form library. ( react-hook-form mình đã được hướng dẫn làm qua course video. Mình build lại form dựa vào hướng dẫn đó.) - User được đưa tới trang `/form` vì chưa login. Nên khi login và submit form này xong mình muốn nó tiếp tục đưa mình đến trang mà ban đầu mình muốn đến. Vì vậy lúc submit form mình sẽ thêm [`navigate()`](https://reactrouter.com/docs/en/v6/hooks/use-navigate) ```javascript function Form() { const onSubmit = (data) => { auth.signin(data.email, () => { // Send them back to the page they tried to visit when they were // redirected to the login page. Use { replace: true } so we don't create // another entry in the history stack for the login page. This means that // when they get to the protected page and click the back button, they // won't end up back on the login page, which is also really nice for the // user experience. navigate(from, { replace: true }); }); return ( <Modal> <FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)> //your code here </FormProvider> </Modal> ) } ``` ### `/contexts` 1. `AuthContext.js` - Bạn dùng đoạn code này, đọc xem nó làm gì. Functions và state trong đây sẽ được lấy ra sử dụng xuyên xuyết app thông qua `useAuth()` ```javascript import React, { useState, useContext, createContext } from "react"; const AuthContextType = { user: "", signin: null, signout: null, }; const AuthContext = createContext(AuthContextType); export function AuthProvider({ children }) { let [user, setUser] = useState(""); let signin = (newUser, callback) => { setUser(newUser); callback(); }; let signout = (callback) => { setUser(null); callback(); }; let value = { user, signin, signout }; return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; } export function useAuth() { return useContext(AuthContext); } ``` ### App.js - Cuối cùng là `App.js` mình sẽ chứa các routes có AuthProvider bọc ngoài cùng để đảm bảo tất cả các route đểu có thể check được state `user` (hoặc sử dụng các function login, login, v.v). - Mình nên xếp các route như thế nào bạn tham khảo StackBlitz này component App. https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal?file=src%2FApp.tsx