React
Create a project
npm create vite@latest project-folder-nameShortcuts
// rafce
// rafc
// rfcNote: Tutorials 1
Note: Tutorials 2
Project: React Jobs (along with Tutorial 2)
-
create a project, update vite.config.ts
-
empty app.tsx, delete app.css, and empty index.css
-
setup tailwind,
vite react tailwind -
reformat the code copied from the index.html into App.tsx
-
reformat with component Navbar.tsx
-
assets/images/logo.png
single page development
- props, default values and constraint types
(props) => {...}or({ isHome = false}) => { ... } - useState,
onClick={() => setSome((prevState) => !prevState)}
additional packages
- react-icon, install additional package
npm i react-icons- remove
import { FaArrowLeft } from 'react-icons/fa'<FaArrowLeft className='mr-2' /> Some Texts
- react-router-dom,
npm i react-router-dom
routing
- within
App.tsx
import {
Route,
createBrowserRouter,
createRoutesFromElements,
RouterProvider,
} from `react-router-dom`;
import HomePage from './pages/HomePage';
const router = createBrowserRouter(
// createRoutesFromElements(<Route index element={<HomePage />} />)
createRoutesFromElements(<Route path='/about' element={<HomePage />} />)
);
const App = () => {
return <RouterProvider router={router} />;
}
export default App;layout
- create folder
pages, including HomePage, … - within
App.tsx, wrap other route with layout route - use
Outletin layout component
- we prefer
link tag, nota tag, becausea tagdoes a complete page refresh - How to change a tag to link tag:
import {Link} from 'react-router-dom' // 1. change all `a` to `Link` // 2. change `href` to `to`
404 page
- create 404 page
- add route with *
active link on NavBar
- use
NavLinkinstead ofLink - className attached with a function
Conditional rendering
- use props and
? :
Mock API
- use json server with our json file
- install: -D means dev dependency
npm i -D json-server - update
package.json- within
scriptsadd"server": "json-server --watch src/jobs.json --port 8888"
- within
- run
npm run server - use
useEffecthook to make a request, we also useuseStateconst [jobs, setJobs] = useState([]);const [loading, setLoading] = useState(true);
useEffect( () => { const fetchJobs = async () => { try { const res = await fetch('http://localhost:8000/jobs'); // without proxy const data = await res.json(); setJobs(data); } catch (error) { console.log('Error fetching', error); } finally { setLoading(false); } } fetchJobs(); }, []); { loading ? ( <Spinner loading={loading} /> ) : ( <> {jobs.map((job) => ( <JobListing key={job.id} job={job} /> ))} </JobListing> ) } - use
React Spinners, install:npm i react-spinners- Ref
- create a spinner ui component
Different approach to fetch data
react suspense, it allows us to do a render while fetching, so we basically provide a fallback UI such as a spinner. (what we are doing here we fetch on render, because when it renders it has a side effect of fetching the data)react queryandSWRare third-party libraries. They make data fetching a little easier.- react 19 has new use hook
Proxying
- with create react app use
package.json - with vite we use
vite.config.ts, and add following inserver
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
// every time we send a request we use /api, i.e. /api/jobs (instead of localhost:00/jobs)
data loader from react router for single page
- another way to fetch data
the traditional way: useEffet way
import {useState, useEffect} from 'react';
import {useParams} from 'react-router-dom';
import Spinner from '../component/Spinner';
const JobPage = () => {
const { id } = useParams();
const [job, setJob] = useState(null);
cont [loading, setLoading] = useState(true);
useEffect( () => {
const fetchJob = async () => {
try {
const res = await fetch(`/api/jobs/${id}`) // use ` here not '
const data = await res.json();
console.log(data);
setJob(data);
} catch (error) {
console.log('Error fetching data', error);
} finally {
setLoading(false);
}
};
fetchJob();
}, []);
return loading ? <Spinner /> : <h1>{job.title}<h1/>
}
export default JobPage;new way: data loader way(a new feature with react router not react itself)
// 5.
import {useParams, useLoaderData} from 'react-router-dom';
const JobPage = () => {
const { id } = useParams();
// 6.
const job = useLoaderData();
// 7.
return <h1>{job.title}<h1/>
}
// 1.
const jobLoader = async ({params}) => {
const res = await fetch(`/api/jobs/${params.id}`) // use ` here not '
const data = await res.json();
return data;
};
// 2.
export { JobPage as default, jobLoader };// within App.tsx
// 3.
import JobPage, {jobLoader} from './pages/JobPage';
// 4. we can pass this jobLoader into other components as well and use that to get a job by its id
...
<Route path='/jobs/:id' element={<JobPage />} loader={jobLoader} />
...Forms
- change
classtoclassName - change
for=tohtmlFor=
Other ways to work with forms, including
foric
- the most common basic way to work with form:
- adding a piece of
useStatefor every field in our form. - if with react 19: we can use
<form action=? > - if with older react: we can use
<form onSubmit =? >
- adding a piece of
pass Functions as props && POST request to Add a job
- we could use context API, we have all request methods in a context file
- or we could use Redux or some other state manager.
- within this app we just put all requests within
App.tsx
toastify
npm i react-toastify