近期更新完毕,建议关注、收藏!
目录
- 快速入门
快速入门
- 前提:安装npm
#npm install react react-dom
conda install nodejs
npm install create-react-app
cd my-app#切换到项目文件夹
npm install
npm i web-vitals --save-dev
#如果上述命令报错,安装web-vitals
npm install web-vitals
#npx create-react-app my-app 这个会报错
react代码主要是在js文件中写的。下面介绍的这种标签语法都成为JSX,
JSX 比 HTML 更加严格。你必须闭合标签,如 < br />。你的组件也不能返回多个 JSX 标签。你必须将它们包裹到一个共享的父级中,比如 < div>…< /div> 或使用空的 <>…</> 包裹
function MyButton() {//创建组件 MyButton
//React 组件必须以大写字母开头,而 HTML 标签则必须是小写字母。
return (
<button>I'm a button</button>
);
}
//export default 关键字指定了文件中的主要组件
//ES6 的模块化语法,用于将某个值(函数、对象、类、变量等)导出
//使得其他模块(文件)可以导入并使用它。
export default function MyApp() {//嵌套在MyApp中
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
//同样可以通过classname指定样式 在css中编写
<img className="avatar" />
//显示变量
return (
<h1>
{user.name}
</h1>
);
//变量属性传递
/*
className="avatar" 是将 "avatar" 字符串传递给 className。
src={user.imageUrl}读取JavaScript 的 user.imageUrl变量,将该值作为 src 属性传递:
*/
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
//综上,例子1:
const user = {
name: 'Hedy Lamarr',
imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
imageSize: 90,
};
export default function Profile() {
return (
<>
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'Photo of ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize
}}
/>
</>
);
}
//style={{}} 并不是一个特殊的语法
//而是 style={ } JSX 大括号内的一个普通 {} 对象。
//条件语句
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
//或者
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
//渲染列表
const products = [
{ title: 'Cabbage', isFruit: false, id: 1 },
{ title: 'Garlic', isFruit: false, id: 2 },
{ title: 'Apple', isFruit: true, id: 3 },
];
export default function ShoppingList() {
const listItems = products.map(product =>
<li
key={product.id}
style={{
color: product.isFruit ? 'magenta' : 'darkgreen'
}}
>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
}
//事件
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
//更新界面
import { useState } from 'react';
export default function MyApp() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
const [count, setCount] = useState(0);
/*
你将从 useState 中获得两样东西:当前的 state(count),以及用于更新它的函数(setCount)。你可以给它们起任何名字,但按照惯例会像 [something, setSomething] 这样为它们命名。
*/
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
- Hook
以 use 开头的函数被称为 Hook。useState 是 React 提供的一个内置 Hook。
你可以在 React API 参考 中找到其他内置的 Hook。
你也可以通过组合现有的 Hook 来编写属于你自己的 Hook。
Hook 比普通函数更为严格。你只能在你的组件(或其他 Hook)的 顶层调用 Hook。
如果你想在一个条件或循环中使用 useState,请提取一个新的组件并在组件内部使用它。
为什么如此严格?
React Hooks 依赖于组件的渲染顺序来正确管理组件的状态。每次组件渲染时,React 会按顺序调用所有 Hooks,如果你把它们放在条件语句或者循环中,可能会导致以下问题:
调用顺序不一致:如果某个 Hook 被包裹在条件语句中,组件的渲染顺序就会变化。例如,第一次渲染时,可能执行了某个 Hook,第二次渲染时由于条件的变化没有执行这个 Hook,导致 React 无法正确地追踪状态或副作用。
状态管理错误:如果 Hooks 的调用顺序发生变化,React 就无法确保每个 Hook 都能正确关联到对应的状态或者副作用,从而引发状态管理和渲染的混乱。
import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0); // 在组件顶层调用 Hook
// 条件语句中的代码不能包含 Hook
if (count > 5) {
console.log("Count is greater than 5");
}
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<p>Count: {count}</p>
</div>
);
}
//错误的使用!!!
import React, { useState } from 'react';
function MyComponent() {
if (count > 5) {
const [count, setCount] = useState(0); // 错误:条件中调用 Hook
}
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<p>Count: {count}</p>
</div>
);
}
在上面的例子中,useState 被放在了 if 语句中,这是错误的做法。条件语句中的 Hook 会根据 count 的值改变,因此在不同的渲染中会导致调用顺序的不一致,React 无法正确跟踪状态。
那我如果就想实现这种条件渲染,应该如何做?
import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0); // 在组件顶层调用 Hook
const handleIncrement = () => {
setCount(count + 1);
};
return (
<div>
{count > 5 && <p>Count is greater than 5</p>} {/* 条件渲染 */}
<button onClick={handleIncrement}>Increment</button>
<p>Count: {count}</p>
</div>
);
}
- 组件间共享数据
为了使得 MyButton 组件显示相同的 count 并一起更新,你需要将各个按钮的 state “向上” 移动到最接近包含所有按钮的组件之中。当你点击任何一个按钮时,MyApp 中的 count 都将改变,同时会改变 MyButton 中的两个 count。
import { useState } from 'react';
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
// const [count, setCount] = useState(0);
//之前是放在这一级的所以两个按钮不一样
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}