github地址代码调试地址
缺少逻辑复用的机制
类组件经常会变得很复杂难以维护
类成员方法不能保证 this 指向的正确性
参数缓存
接受唯一的参数
即状态初始值,初始值可以是任意数据类型返回值为数组
,数组中存储值和更改状态值的方法,方法名称约定以 set 开头,后面加上状态名称。只在第一次渲染的时候执行一次
,参数可以是函数,只会被调用一次设置状态值的方法是异步的
import {
useState} from 'react'
function App() {
const [count, setCount] = useState(0)
return (
<div>
<span>{
count}</span>
<button onClick={
()=>setCount(count+1)}> + 1</button>
</div>
);
}
export default App;
import {
useReducer } from "react";
function App() {
// useReducer => 提供redux
function reducer (state,action){
switch (action.type) {
case 'increment':
return state+1
case 'decrement':
return state-1
default:
return state;
}
}
const [countState ,dispatch] = useReducer(reducer,0)
return (
<div className="App">
<span>{
countState}</span>
<button onClick={
()=>dispatch({
type:'increment'})}>+1</button>
<button onClick={
()=>dispatch({
type:'decrement'})}>-1</button>
</div>
);
}
export default App;
import {
createContext,useContext } from "react";
function App() {
// createContext 方便跨组件层级传值
// useContext 简化接受传值组件的代码
const countContext = createContext();
function Foo () {
const value = useContext(countContext)
return <div>{
value}</div>
//
// {
// value => {
// return {value}
// }
// }
//
}
return (
<div className="App">
<countContext.Provider value={
100}>
<Foo />
</countContext.Provider>
</div>
);
}
export default App;
useEffect(() => {}) :
组件挂载完成, 组件更新完 执行useEffect(() => {}, []) :
组件挂载完成 执行useEffect(() => () => {}) :
组件更新完,组件将要卸载 执行useEffect(() => () => {},[]) :
组件将要卸载 执行useEffect(() => {}, [xxx])
:只有指定数据发生变化时触发 effect // useEffect 异步函数的使用
function getData (){
return new Promise((resolve)=>{
resolve(100)
})
}
// 可以
useEffect(()=>{
getData().then(result=>{
console.log(result)
})
},[])
// 添加函数自执行 使用异步函数
useEffect(()=>{
(async function(){
const result = await getData();
console.log(result)
})()
},[])
import {
useState, useMemo,memo } from "react";
function App() {
const [countEf,setCountEf] = useState(1);
const compute = useMemo(()=>{
return countEf*2},[countEf])
return (
<div className="App">
<span>计算属性{
compute}<Child></Child></span>
</div>
);
}
// memo 没有状态更新不让子组件渲染
const Child = memo(function Child() {
console.log('Child组件重新渲染了')
return <div>我是Child组件</div>
})
export default App;
export default function App () {
const [count, setCount] = useState(0)
const resetCount = useCallback(() => {
setCount(0)
}, [setCount])
return (
<div>
<span>{
count}</span>
<button onClick={
() => setCount(count + 1)}> + 1</button>
<Foo resetCount={
resetCount} />
</div>
)
}
import {
useRef } from "react";
export default function App () {
const box = useRef()
return (
<div ref={
box}>
<button onClick={
() => console.log(box)}> DIV </button>
</div>
)
}
import {
useRef, useState, useEffect} from "react";
export default function App () {
const [count, setCount] = useState(0)
let timeId = useRef() // 夸组件生命周期
useEffect(() => {
// 使用这个 ref 的 current 属性存储数据
timeId.current = setInterval(() => {
setCount(count => count + 1)
}, 1000);
}, [])
const stopCount = () => {
console.log(timeId.current)
clearInterval(timeId.current)
}
const box = useRef()
return (
<div ref={
box}>
<span>{
count}</span>
<button onClick={
() => stopCount()}> 停止 </button>
</div>
)
}
// 基本用法
import {
useState, useEffect} from "react";
import axios from "axios";
function useGetPost () {
const [post, setPost] = useState({
})
useEffect(() => {
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => {
setPost(response.data)
})
}, [])
return [post, setPost]
}
export default function App () {
const [post, setPost] = useGetPost()
return (
<div>
<h1>{
post.title}</h1>
<div>{
post.body}</div>
</div>
)
}
// 封装公共逻辑
import {
useState} from "react";
function useUpdateInput (initialState) {
const [value, setValue] = useState(initialState)
return {
value,
onChange: e => setValue(e.target.value)
}
}
export default function App () {
const usernameInput = useUpdateInput('')
const passwordInput = useUpdateInput('')
const submitForm = event => {
event.preventDefault();
console.log(usernameInput.value)
console.log(passwordInput.value)
}
return (
<form onSubmit={
submitForm}>
<input type="text" name="username" {
...usernameInput} />
<input type="password" name="password" {
...passwordInput} />
<input type="submit" />
</form>
)
}
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router } from "react-router-dom";
import App from './App';
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
// home.js
import {
useHistory, useLocation, useRouteMatch, useParams } from "react-router-dom";
export default function Home(props) {
console.log(props)
console.log(useHistory())
console.log(useLocation())
console.log(useRouteMatch())
console.log(useParams())
return <div>
<h1>Home works</h1>
</div>;
}
// list.js
export default function List(props) {
console.log(props)
return <div>
<h1>List works</h1>
</div>;
}
// app.js
import {
Link, Route } from "react-router-dom";
import Home from './pages/Home'
import List from './pages/List'
export default function App () {
return (
<>
<div>
<Link to="/home/zhangsan">首页</Link>
<Link to="/list">列表页</Link>
</div>
<div>
<Route path="/home/:name" component={
Home} />
<Route path="/list" component={
List} />
</div>
</>
)
}