快速入门React
本文最后更新于 2025-04-17,文章内容可能已经过时。
react是一个用于构建用户界面的前端框架,具有很丰富的生态工具,包括ReactRouter AntDesign Redux Next
项目创建
create-react-app
create-react-app是一个用于快速构建 react app 的脚手架,底层是基于webpack构建!
创建一个
react app项目
npx create-react-app my-app在
自定义好一个项目目录文件夹内,通过bash窗口来执行npx命令来创建一个react app项目!
cd my-app
npm start进入
项目内部,执行npm start即可启动项目!
项目目录
创建完项目后,除了index.js和App.js以外多余的删掉即可,记得把引用的静态资源文件路径在App.js中删除掉,避免无法找到该文件报错!
├── package-lock.json
├── package.json
├── public # 静态文件
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── README.md
└── src # 源代码文件
├── App.js
└── index.js # 入口文件index.js
index.js是入口文件,react和react-dom是核心包!
ReactDom获取publc -> index.html中id为root的根元素,并将App.js内容挂载到根节点!
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);App.js
function App() {
return (
<div className="App">
<center>
<h1>Welcome to React!</h1>
</center>
</div>
);
}
export default App;基础内容
jsx 基础
jsx是xml和html的一个缩写方式,可以通过标签的写法,在其内部可通过{ }大括号来访问js中提供的变量信息,是React UI编写模版的一种方式!
const message = "Welcome to React!";
function App() {
return (
<div className="App">
<center>
<h1>{message}</h1>
</center>
</div>
);
}
jsx语法本身在浏览器端是不被识别的,需要通过babel工具,将jsx转换为浏览器能够认识的代码!
识别js表达式
在
jsx中使用表达式,只需要在{ 表达式 }花括号中使用即可,类似于模版字符串${ },可识别字符串、js变量、函数调用返回值、以及对象方法的调用!
const message = "Welcome to React!";
function test(){
return 'test text';
}
function App() {
return (
<div className="App">
<center>
<h1>{"Hello, World!"}</h1>
<h1>{message}</h1>
<h1>{test()}</h1>
<h1>{new Date().toLocaleString()}</h1>
<h1>{Math.random()}</h1>
<h1>{[1, 2, 3, 4, 5].map(num => <p key={num}>{num}</p>)}</h1>
<h1 style={{color: 'blue'}}>测试样式</h1>
</center>
</div>
);
}
列表渲染
列表渲染,
key属性是必要的,必须是唯一值!
const list = [
{id: 1, name: 'apple'},
{id: 2, name: 'banana'},
{id: 3, name: 'orange'},
{id: 4, name: 'grape'},
]<ul>
{list.map(item => <li key={item.id}>{item.name}</li>)}
</ul>条件渲染
{flag && <h1>Flag is true</h1>}
{!flag && <h1>Flag is false</h1>}
{flag ? <h1>Flag is false</h1> : <h2>Flag is true</h2>}事件绑定
function handleClick(){
console.log('clicked');
}
<button onClick={handleClick}>Click me</button>参数绑定
function handleClick(name, e){
console.log('clicked');
}
<button onClick={(e) => handleClick("name", e)}>Click me</button>React 函数组件
组件,一般用来将重复的视图部分,提取出一个公共的组件,供其他视图模块使用,在React中,定义一个组件都可视为一个函数(Function)且函数名首字母需要大写!
定义一个
button组件,components -> button -> index.js
function Button(props) {
return <button className="btn">{props.text}</button>;
}
export default Button;在其它组件中使用
import Button from "./components/button";
const message = "Welcome to React!";
let flag = true;
function test(){
return 'test text';
}
const list = [
{id: 1, name: 'apple'},
{id: 2, name: 'banana'},
{id: 3, name: 'orange'},
{id: 4, name: 'grape'},
]
function handleClick(){
console.log('clicked');
}
function App() {
return (
<div className="App">
<center>
<h1>{"Hello, World!"}</h1>
<h1>{message}</h1>
<h1>{test()}</h1>
<h1>{new Date().toLocaleString()}</h1>
<h1>{Math.random()}</h1>
<h1>
{[1, 2, 3, 4, 5].map((num) => (
<p key={num}>{num}</p>
))}
</h1>
<h1 style={{ color: "blue" }}>测试样式</h1>
<ul>
{list.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
{flag && <h1>Flag is true</h1>}
{!flag && <h1>Flag is false</h1>}
{flag ? <h1>Flag is false</h1> : <h2>Flag is true</h2>}
<button onClick={(e) => handleClick("name", e)}>Click me</button>
<div className="">
自定义组件
<Button text="Hello, World!" />
</div>
</center>
</div>
);
}
export default App;useState 状态变量
useState在React中是一个状态变量,主要用于更新视图,可理解为响应式,当数据发生变化时,通过useState函数来更新视图!类似于
vue3中的ref和reactive将变量转换为响应式!
// const [count, setCount] = useState(0); 不能在这定义 useState ❎
function App() {
const [count, setCount] = useState(0); // 必须在函数组件内部定义 useState ✅
return (
<div className="App">
<center>
<div className="custom-component">
{count + 1}
<button onClick={() => setCount(count + 1)}>useState 状态变量</button>
</div>
</center>
</div>
);
}
useState可接受一个初始值的参数,返回一个数组,其中第一个是状态变量,第二个是更新状态变量的函数,当数据需要改变时,调用setCount函数更新视图!
需要注意的是,
useState Hooks函数必须在组件函数内部使用!
修改复杂类型
修改
引用类型时,需要始终返回一个新的对象地址修改才行,避免修改时影响对源对象引用地址!
import { useState } from "react";
function App() {
const [ user, setUser ] = useState({ name: "Miao", age: 25 });
function modifyUser(){
// 参数传递一个新的对象,并对原有的属性进行覆盖,而不是在原有对象的地址上进行修改
setUser({...user, age: user.age + 1});
}
return (
<div className="App">
<center>
<div className="custom-component">
<p>{user.name} {user.age}</p>
<button onClick={modifyUser}>useState 修改对象</button>
</div>
</center>
</div>
);
}
export default App;
组件样式控制
使用
行内样式行内样式,
多单词之间使用驼峰命名!<ul style={{ listStyle: "none", fontSize: "20px", color: "red" }}> {list.map((item) => ( <li key={item.id}>{item.name}</li> ))} </ul>使用类样式
className.app{ border: 1px solid red; }import './index.css' fucntion App(){ return ( <div className = "app"> 类样式 </div> ) }
todoListDemo
index.css
.list{
border: 1px solid #ccc;
}
.list .item{
padding: 10px;
}
.list .item:not(:last-child){
border-bottom: 1px solid #ccc;
}import { useState } from "react";
import "./styles/index.css"
const list = [
{ id: 1, name: "apple" },
{ id: 2, name: "banana" },
{ id: 3, name: "orange" },
{ id: 4, name: "grape" },
];
function App() {
const [items, setItems] = useState(list);
return (
<div className="App">
<center>
<h1>{"Hello, World!"}</h1>
<button onClick={() => setItems([...items, { id: items.length + 1, name: "new item" }])}>新增</button>
<div className="list">
{items.map((item) => (
<div key={item.id} className="item">
<h2>{item.name}</h2>
<div className="btn" style={{textAlign: "right"}}>
<button onClick={() => setItems(items.filter((i) => i.id !== item.id))}>
Delete
</button>
</div>
</div>
))}
</div>
</center>
</div>
);
}
export default App;classname动态类名优化
在
React中,避免不了有些类名是需要条件切换的,通常会根据某一个条件来判断当前类名是否显示与否,比如,当前激活元素active设置为高亮,通常会通过${ currentIndex === index && 'active' },如果动态类名多了,看起来就比较费劲,这时需要classname这个第三方插件,来改写下方式,减少复杂度!
安装插件
npm install classname插件用法

表单数据绑定
表单
数据绑定,就是数据双向绑定,当输入内容时,将数据同步到状态变量中,当状态变量发生变化时,会同时修改input中的value值!
大概原理与
vue中的v-model语法糖一致,vue中会通过v-bind的方式,来绑定value值,且通过input事件将值$emit出去并修改!
const [value, setValue] = useState("");
<input value = {value} @change="(e) => setValue(e.target.value)" type="text" />useRef获取dom
在
React中,获取dom需要通过useRef Hooks函数来生成一个ref引用,对目标元素进行一个ref绑定!
import { useRef, useState } from "react";
function App() {
const appRef = useRef(null);
return (
<div className="App" ref={appRef}>
<center>
<button onClick={() => console.log(appRef.current.getBoundingClientRect())}>点击获取dom</button>
</center>
</div>
);
}
export default App;通过
appRef.current属性来获取dom,操作dom时需要等待dom完全渲染完成后才能使用!
组件传递
父子通信
通过
props里实现父子组件通信
function Button(props) {
return <button className="btn">{props.text}</button>;
}
function Parent() {
let text = "新增";
return <Button text={text} />;
}
子父通信
子传父,在React中,通过父组件向子组件传递函数,且在子组件来当做参数来调用父组件函数!
function Button(props) {
let childrenMsg = 'children msg!';
return <button className="btn" onClick={() => props.getMessage(childrenMsg)}>{props.text}</button>;
}
function Parent() {
let text = "新增";
function getMessage(msg){
}
return <Button text={text} onGetMessage={ getMessage } />;
}兄弟通信
使用
状态提升,可以完成兄弟之间通信,状态提升,就是父组件,将子组件中的数据,获取到,并通过父传子的方式,到另一个子组件,便可完成跨兄弟组件通信!
import { useState } from "react";
function Children1(props) {
console.log("Children1 props", props);
return <div>children1 {props.childrenMsg}</div>;
}
function Children2(props) {
let childrenMsg = 'Children2'
return (
<div>
{childrenMsg}
<button
className="btn"
onClick={() => props.onGetChildren2Msg(childrenMsg)}
>
Children2
</button>
</div>
);
}
function Button(props) {
const [ msg, setMsg ] = useState('');
const getChildren2Msg = ( msg ) => {
setMsg(msg);
console.log('parent Button', msg);
}
return (
<div>
<Children1 childrenMsg={msg} />
<Children2 onGetChildren2Msg={getChildren2Msg} />
<button className="btn">{props.text}</button>
</div>
);
}
export default Button;跨组件通信
跨组件通信使用
Context机制实现跨层传递!
创建
createContext()返回一个上下文在
根组件中,使用Provider来提供数据在
子组件或孙子组件中,通过useContext来获取上下文提供的数据!
import { createContext, use, useContext, useState } from "react";
// 创建 createContext 上下文
const MsgContext = createContext();
function Children1(props) {
console.log("Children1 props", props);
// 使用useContext获取上下文,获取 provider 提供的数据
const msg = useContext(MsgContext);
console.log("Children1 msg 跨层传递消息 useContext", msg);
return <div>children1 {props.childrenMsg}</div>;
}
function Children2(props) {
let childrenMsg = 'Children2'
// props.getChildren2Msg(childrenMsg);
return (
<div>
{childrenMsg}
<button
className="btn"
onClick={() => props.onGetChildren2Msg(childrenMsg)}
>
Children2
</button>
</div>
);
}
function Button(props) {
const [ msg, setMsg ] = useState('');
const getChildren2Msg = ( msg ) => {
setMsg(msg);
console.log('parent Button', msg);
}
return (
<div>
<!-- 在根组件中使用 provider 向外提供数据-->
<MsgContext.Provider value={{ msg, setMsg }}>
<Children1 childrenMsg={msg} />
<Children2 onGetChildren2Msg={getChildren2Msg} />
</MsgContext.Provider>
<button className="btn">{props.text}</button>
</div>
);
}
export default Button;useEffect
useEffect主要用来处理副作用的,主要处理与渲染无关的逻辑,比如数据请求、dom操作、事件监听等相关逻辑!
useEffect有两个参数,一个是回调函数,另一个是依赖项数组!useEffect(()=> {}, [])
useEffect会在每次渲染完成后执行调用,当设置第二个参数为依赖空数组时,则只会在第一次渲染结束后执行!
当依赖项数组不为空时,则会在依赖项发生变化时,触发调用!
依赖项: 就是页面中所展示依赖的数据项,页面数据发生变化时,触发操作!
import { useEffect, useState } from "react";
import "./styles/index.css"
function App() {
const [ counter, setCounter ] = useState(0);
// 不传入依赖项,useEffect在每次渲染时都会执行
/* useEffect(() => {
console.log("Hello, World!");
}); */
// 传入空数组,useEffect只会在第一次渲染时执行
/* useEffect(() => {
console.log("Hello, World!");
}, []); */
// 传入依赖项,useEffect只在counter变化时才会执行
useEffect(() => {
console.log("counter changed:", counter);
}, [counter]);
return (
<div className="App">
<center>
<h1>{("Hello, World!", counter)}</h1>
<button onClick={() => setCounter(counter + 1)}>+</button>
</center>
</div>
);
}
export default App;useEffect 清除副作用
在
useEffect内部可以返回一个函数,在函数内部可以实现组件卸载后,执行一些逻辑操作,比如清除定时器,以及移除事件监听相关操作!
useEffect(() => {
console.log("counter changed:", counter);
const timer = setInterval(() => {
setCounter(counter + 1);
}, 1000);
return () => {
// 清除副作用
clearInterval(timer);
}
}, [counter]);Hooks
Hooks是函数封装的一个概念,将复用逻辑提取到函数中进行处理后返回结果!
Hooks函数的定义需要以useXxx的方式去定义!
import { useState } from "react";
import "./styles/index.css"
function useToggle(){
const [ isOn, setIsOn ] = useState(false);
const toggle = () => setIsOn(!isOn);
return [ isOn, toggle ];
}
function App() {
const [ counter, setCounter ] = useState(0);
const [ isOn, toggle ] = useToggle();
return (
<div className="App">
<center>
<h1>{isOn ? "ON" : "OFF"}</h1>
<button onClick={toggle}>Toggle</button>
</center>
</div>
);
}
export default App;Hooks 使用规范
Hooks只能在组件函数内部使用,且必须是顶层,不能包含在if和for以及其他函数模块中使用!
- 不能在组件外部使用
import { useState } from "react"; import "./styles/index.css" function useToggle(){ const [ isOn, setIsOn ] = useState(false); const toggle = () => setIsOn(!isOn); return [ isOn, toggle ]; } const [ isOn, toggle ] = useToggle(); // no ❎ function App() { const [ counter, setCounter ] = useState(0); // const [ isOn, toggle ] = useToggle(); // yes ✅ return ( <div className="App"> <center> <h1>{isOn ? "ON" : "OFF"}</h1> <button onClick={toggle}>Toggle</button> </center> </div> ); } - 不能在条件语句内使用
import { useState } from "react"; import "./styles/index.css" function useToggle(){ const [ isOn, setIsOn ] = useState(false); const toggle = () => setIsOn(!isOn); return [ isOn, toggle ]; } function App() { if( true ){ const [ counter, setCounter ] = useState(0); const [ isOn, toggle ] = useToggle(); // yes ❎ } return ( <div className="App"> <center> <h1>{isOn ? "ON" : "OFF"}</h1> <button onClick={toggle}>Toggle</button> </center> </div> ); }