React18项目实战:从零开始的完整指南
本文详细介绍了从零开始使用React 18进行项目开发的全过程,包括环境搭建、组件创建、状态管理、路由配置以及API数据请求等内容。同时,还涵盖了项目的打包部署和性能优化技巧,帮助你全面掌握React 18项目实战。React 18项目实战涉及的知识点全面且实用,适合初学者和有一定经验的开发者参考。
React 18 项目实战:从零开始的完整指南 React 18基础入门介绍React及其最新版本React 18
React 是由 Facebook 开发并维护的一个用于构建用户界面的 JavaScript 库。React 致力于提高开发效率与用户体验,通过声明式设计高效地构建用户界面,遵循“渐进式增强”的设计思路,使得开发者可以逐步提升应用的复杂度和性能。最新的 React 版本 React 18 带来了许多新特性,比如支持并发模式,改进了SSR和代码分割等,使得React在性能和易用性上得到了进一步的提升。
安装Node.js和npm
在开始使用React之前,需要先安装Node.js和npm(Node Package Manager)。Node.js 是一个开源的、跨平台的 JavaScript 运行环境,可以运行在服务端。npm 是 Node.js 的包管理器,可以通过 npm 安装和管理 React 和其他相关库。
- 访问 Node.js 官方网站 下载最新版本的 Node.js。
- 安装Node.js时,会自动安装npm。
检查安装是否成功:
node -v
npm -v
确保 Node.js 和 npm 已经正确安装。
使用Create React App快速搭建项目环境
Create React App 是一个官方推荐的脚手架工具,用于快速搭建 React 项目。它提供了开箱即用的设置,包括构建工具、测试框架和开发服务器等功能。
- 打开终端(命令行工具)。
- 使用 npm 安装 Create React App 的命令行工具:
npm install -g create-react-app
- 使用 Create React App 创建一个新的 React 项目:
npx create-react-app my-app
这会创建一个名为 my-app
的 React 项目,并自动安装必要的依赖。
- 进入项目目录:
cd my-app
- 启动开发服务器:
npm start
此时,浏览器会自动打开 http://localhost:3000
,展示新的 React 项目。
创建简单的React组件
在 React 中,组件是构建用户界面的基本单位。每个组件通常包含一个输入(props)和一个输出(描述 UI 的 HTML 标签)。
- 在
src/components
目录下创建一个名为HelloWorld.js
的新文件。 - 编写一个简单的函数组件:
// src/components/HelloWorld.js
import React from 'react';
function HelloWorld() {
return <h1>Hello, World!</h1>;
}
export default HelloWorld;
- 在
App.js
文件中引入并使用该组件:
// src/App.js
import React from 'react';
import HelloWorld from './components/HelloWorld';
function App() {
return (
<div className="App">
<HelloWorld />
</div>
);
}
export default App;
此时,浏览器中的应用会显示 "Hello, World!"。
React组件开发组件的分类:函数组件和类组件
在 React 中,有两种主要的组件类型:函数组件和类组件。
函数组件
函数组件是最简单的组件类型,它们是接收 props 作为输入并返回一个 UI 组件的函数。
// src/components/FuncComponent.js
import React from 'react';
function FuncComponent(props) {
return <h1>Hello, {props.name}!</h1>;
}
export default FuncComponent;
类组件
类组件是基于 ES6 类语法的组件,它不仅接收 props 作为输入,还可以包含内部状态和生命周期方法。
// src/components/ClassComponent.js
import React, { Component } from 'react';
class ClassComponent extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default ClassComponent;
组件的属性(Props)和状态(State)
属性(Props)
属性是父组件传递给子组件的数据。子组件通过 props 接收数据,使用这些数据来渲染 UI。
// src/App.js
import React from 'react';
import HelloWorld from './components/HelloWorld';
function App() {
return (
<div className="App">
<HelloWorld name="Alice" />
<HelloWorld name="Bob" />
</div>
);
}
export default App;
状态(State)
状态是组件内部的数据,用于控制组件的行为。状态应该被视为不可变的,只能通过 setState 来更新。
// src/components/Counter.js
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default Counter;
使用Hooks简化组件开发
React Hooks 是 React 16.8 引入的新特性,允许我们在不编写类的情况下使用状态和其他 React 特性。主要的 Hooks 包括 useState
、useEffect
、useContext
等。
使用 useState
useState
允许我们在函数组件中使用状态。
// src/components/UseStateCounter.js
import React, { useState } from 'react';
function UseStateCounter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
</div>
);
}
export default UseStateCounter;
使用 useEffect
useEffect
允许我们执行副作用操作,如订阅、设置定时器、发送网络请求等。
// src/components/UseEffectExample.js
import React, { useState, useEffect } from 'react';
function UseEffectExample() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default UseEffectExample;
状态管理和数据流
父子组件间的状态传递
在 React 中,可以使用 props 将状态从父组件传递给子组件。
// src/components/ParentComponent.js
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
function ParentComponent() {
const [message, setMessage] = useState('Hello from Parent');
return (
<ChildComponent message={message} />
);
}
export default ParentComponent;
// src/components/ChildComponent.js
import React from 'react';
function ChildComponent(props) {
return <h1>{props.message}</h1>;
}
export default ChildComponent;
使用Context API管理全局状态
Context API 用于在组件树中传递数据。它避免了在组件树中进行 prop drilling(即层层传递 props)。
// src/Context.js
import React, { createContext, useContext, useState } from 'react';
const MyContext = createContext();
function MyProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<MyContext.Provider value={{ theme, setTheme }}>
{children}
</MyContext.Provider>
);
}
export const useMyContext = () => useContext(MyContext);
export { MyProvider };
// src/App.js
import React from 'react';
import MyProvider from './Context';
import ChildComponent from './ChildComponent';
function App() {
return (
<MyProvider>
<ChildComponent />
</MyProvider>
);
}
export default App;
// src/components/ChildComponent.js
import React from 'react';
import { useMyContext } from '../Context';
function ChildComponent() {
const { theme, setTheme } = useMyContext();
return (
<div>
<h1>{theme}</h1>
<button onClick={() => setTheme('dark')}>Toggle Theme</button>
</div>
);
}
export default ChildComponent;
状态管理库Redux的基本使用
Redux 是一个用于 JavaScript 应用的状态管理库,它通过单一的 store 来管理应用的所有状态。
- 安装 Redux 相关库:
npm install redux react-redux
- 创建 Redux Store:
// src/store.js
import { createStore } from 'redux';
const initialState = {
counter: 0,
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return { counter: state.counter + 1 };
case 'DECREMENT':
return { counter: state.counter - 1 };
default:
return state;
}
};
const store = createStore(rootReducer);
export default store;
- 创建 Redux 连接组件:
// src/components/Counter.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from '../actions';
function Counter() {
const counter = useSelector((state) => state.counter);
const dispatch = useDispatch();
return (
<div>
<h1>Count: {counter}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
}
export default Counter;
- 在
App.js
中使用Provider
:
// src/App.js
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './components/Counter';
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
export default App;
路由与导航
使用React Router进行页面路由配置
React Router 是一个用于 React 应用的路由库。它允许你定义应用的不同页面,并使用这些页面进行导航。
- 安装 React Router:
npm install react-router-dom
- 配置路由:
// src/App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import Contact from './components/Contact';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
</div>
</Router>
);
}
export default App;
- 创建页面组件:
// src/components/Home.js
import React from 'react';
function Home() {
return <h2>Home Page</h2>;
}
export default Home;
// src/components/About.js
import React from 'react';
function About() {
return <h2>About Page</h2>;
}
export default About;
// src/components/Contact.js
import React from 'react';
function Contact() {
return <h2>Contact Page</h2>;
}
export default Contact;
实现单页面应用中的多页面跳转
在 React Router 中,通过不同的路径配置可以实现页面的跳转。
// src/App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, Redirect } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import Contact from './components/Contact';
import NotFound from './components/NotFound';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
<li>
<Link to="/notfound">Not Found</Link>
</li>
</ul>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<Route path="/notfound" component={NotFound} />
<Redirect to="/" />
</Switch>
</div>
</Router>
);
}
export default App;
路由参数传递与使用
React Router 支持传递和使用路由参数。
// src/App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, useParams } from 'react-router-dom';
import Home from './components/Home';
import User from './components/User';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/user/1">User 1</Link>
</li>
<li>
<Link to="/user/2">User 2</Link>
</li>
</ul>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/user/:id" component={User} />
</Switch>
</div>
</Router>
);
}
export default App;
// src/components/User.js
import React from 'react';
import { useParams } from 'react-router-dom';
function User() {
const { id } = useParams();
return <h2>User: {id}</h2>;
}
export default User;
请求API数据
使用fetch和axios发送HTTP请求
fetch
是浏览器内置的用于发送 HTTP 请求的方法,axios
是一个常用的 HTTP 客户端库。
使用 fetch
// src/components/FetchData.js
import React, { useEffect, useState } from 'react';
function FetchData() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => response.json())
.then((data) => setData(data))
.catch((error) => console.error(error));
}, []);
return (
<div>
{data ? <pre>{JSON.stringify(data, null, 2)}</pre> : 'Loading...'}
</div>
);
}
export default FetchData;
使用 axios
// src/components/AxiosData.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function AxiosData() {
const [data, setData] = useState(null);
useEffect(() => {
axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => setData(response.data))
.catch((error) => console.error(error));
}, []);
return (
<div>
{data ? <pre>{JSON.stringify(data, null, 2)}</pre> : 'Loading...'}
</div>
);
}
export default AxiosData;
处理异步数据和错误处理
在处理异步数据时,需要关注请求的响应和错误处理。
// src/components/FetchDataWithError.js
import React, { useEffect, useState } from 'react';
function FetchDataWithError() {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then((data) => setData(data))
.catch((error) => {
setError(error);
console.error('There was an error!', error);
});
}, []);
if (error) {
return <div>Error: {error.message}</div>;
}
if (!data) {
return <div>Loading...</div>;
}
return (
<div>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
export default FetchDataWithError;
实现数据的实时更新
使用 useEffect
和 setState
,可以实现数据的实时更新。
// src/components/RealtimeData.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function RealtimeData() {
const [data, setData] = useState(null);
useEffect(() => {
const intervalId = setInterval(() => {
axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => setData(response.data))
.catch((error) => console.error(error));
}, 5000);
return () => clearInterval(intervalId);
}, []);
if (!data) {
return <div>Loading...</div>;
}
return (
<div>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
export default RealtimeData;
项目部署与优化
项目打包与部署
使用 npm run build
命令打包项目,生成的 build
目录下的文件可以直接部署到生产环境。
npm run build
生成的文件可以部署到任何静态文件服务器,如 AWS S3、Netlify、Vercel 等。
使用AWS S3部署
aws s3 cp build/ s3://your-bucket-name --recursive
使用Netlify部署
netlify deploy --dir=build
使用Vercel部署
vercel --prod
性能优化技巧
- 代码分割:使用
import()
语法进行动态导入,按需加载模块。
import("./myComponent").then(module => {
const MyComponent = module.default;
render(<MyComponent />);
});
- 懒加载:使用 React Router 的
lazy
函数实现组件的懒加载。
import React from 'react';
const MyComponent = React.lazy(() => import('./MyComponent'));
function App() {
return (
<React.Suspense fallback={<div>Loading...</div>}>
<MyComponent />
</React.Suspense>
);
}
- SSR(服务器端渲染):使用 Next.js 或 Gatsby 等框架实现服务器端渲染,提升首屏加载速度。
import { useRouter } from 'next/router';
import React from 'react';
function MyComponent() {
const router = useRouter();
const { id } = router.query;
// fetch data using id
return <div>Component with {id}</div>;
}
export async function getServerSideProps(context) {
const { id } = context.query;
// fetch data using id
return { props: { id } };
}
export default MyComponent;
- 缓存:利用浏览器缓存、服务端缓存等技术减少不必要的请求。
res.setHeader('Cache-Control', 's-maxage=31536000, stale-while-revalidate=2592000');
- 压缩:通过压缩静态资源文件,减小文件体积,加快加载速度。
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: 'images/',
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
};
使用环境变量
环境变量可以帮助你在开发和生产环境中使用不同的配置。
- 创建
.env
文件:
# .env
REACT_APP_API_URL=https://api.example.com
REACT_APP_ENV=development
- 在代码中使用环境变量:
import React from 'react';
import axios from 'axios';
const apiBaseUrl = process.env.REACT_APP_API_URL;
function MyComponent() {
return <div>API URL: {apiBaseUrl}</div>;
}
export default MyComponent;
以上内容详细介绍了从零开始使用 React 18 创建一个完整项目的整个过程,包括安装环境、创建组件、状态管理、路由配置、数据请求、项目部署与优化等。希望对你有所帮助。
共同学习,写下你的评论
评论加载中...
作者其他优质文章