我们在第一天了解到了React的class组件,function组件
组件的传值方式(子传父,父传子)
常用的两个hook:
今天继续学习React,让我们抓住最后一天的时间,一起来速成React吧!
const [val, setVal] = useState('asd')
return (
<div>
<input type="text" value={val} onChange={(e) => { setVal(e.target.value) }} />
<button onClick={() => console.log(val)}>获取input的值</button>
</div>
)
我们对比看一下两者的区别!!!
不受控组件意味着表单元素的value无法通过state获取,只能使用ref(或useRef)来获取
const [val, setVal] = useState('asd')
const element = useRef(null)
return (
<div>
<h3>受控组件:</h3>
<input type="text" value={val} onChange={(e) => { setVal(e.target.value) }} />
<button onClick={() => console.log(val)}>获取input的值</button>
<hr />
<h3>不受控组件:</h3>
<input type="text" ref={element} />
<button onClick={() => console.log(element.current.value)}>获取input的值</button>
</div>
)
import React, { useState, memo } from 'react'
const Child = memo(() => {
console.log(123);
return <div>子组件</div>
})
export default function App11 () {
const [num, setNum] = useState(1)
return (
<div>
<h3>数字为:{num}</h3>
<button onClick={() => setNum(num + 1)}>累加</button>
<hr />
<Child />
</div>
)
}
使用memo后,累加不再log123
import React, { useState, memo, useCallback } from 'react'
const Child = memo((props) => {
console.log(123);
return <button onClick={() => props.doSth()}>累加</button>
})
export default function App11 () {
const [num, setNum] = useState(1)
// const doSth = useCallback(() => setNum(num + 1), [])
const doSth = useCallback(() => {
setNum(num => num + 1)
}, [])
return (
<div>
<h3>数字为:{num}</h3>
<Child doSth={doSth} />
</div>
)
}
函数中返回函数:高阶函数
const doSth = useMemo(() => {
return () => setNum(num => num + 1)
}, [])
听说和vuex差不多,不知道会不会像pinia一样方便
npm i redux react-redux
在src
下新建一个store文件夹
// 创建初始状态
const defaultState = {
num: 1
}
// 导出一个函数
// eslint-disable-next-line import/no-anonymous-default-export
export default (state = defaultState) => {
return state
}
// 引入reducer
import reducer from './reducer'
// 创建仓库
import { createStore } from 'redux'
const store = createStore(reducer)
// 导入仓库
export default store
import { Provider } from 'react-redux'
import store from './store'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
,
document.getElementById('root')
)
import { connect } from 'react-redux'
function App12 (props) {
return (
<div>
<h2>数字为:{props.num}</h2>
</div>
)
}
const mapStateToProps = (state) => {
return {
num: state.num
}
}
export default connect(mapStateToProps)(App12)
export default (state = defaultState, action) => {
let newState = JSON.parse(JSON.stringify(state))
if (action.type === 'addNum') {
newState.num++
}
return newState
}
function App12 (props) {
return (
<div>
<h2>数字为:{props.num}</h2>
<button onClick={() => props.add()}>累加</button>
</div>
)
}
const mapStateToProps = (state) => {
return {
num: state.num
}
}
const mapDispatchToProps = (dispatch) => {
return {
add () {
const action = { type: "addNum" }
dispatch(action)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App12)
const action = { type: "addNum", value: 2 } // action多指定参数
newState.num += action.value // 使用的时候直接action.访问
// if (action.type === 'addNum') {
// newState.num += action.value
// }
switch (action.type) {
case "addNum":
newState.num += action.value
break
default: break
}
yarn add react-router-dom@6
或者npm install react-router-dom
在src
下新建一个route/index.js
文件
主要是三个函数
import App from '../App13'
import Home from '../pages/Home'
import List from '../pages/List'
import Detail from '../pages/Detail'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
/**
* App>Home+List+Detail
* react-router-dom 中有两种模式 : BrowserRouter(History模式) HashRouter(Hash模式)
*/
// 定义一个路由
const BaseRouter = () => (
<BrowserRouter>
<Routes>
<Route path='/' element={<App />}>
<Route path='/home' element={<Home />}></Route>
<Route path='/list' element={<List />}></Route>
<Route path='/detail' element={<Detail />}></Route>
</Route>
</Routes>
</BrowserRouter>
)
export default BaseRouter
import Router from './route/index'
Outlet
组件,并使用,这样可以显示子路由import { Outlet } from 'react-router-dom'
import { Outlet, Link } from 'react-router-dom'
<ul>
<li><Link to="/home">首页</Link></li>
<li><Link to="/list">列表页</Link></li>
<li><Link to="/detail">详情页</Link></li>
</ul>
const location = useLocation()
console.log(location.pathname);
import { Outlet, Link, useLocation, useNavigate } from 'react-router-dom'
const naviate = useNavigate()
<button onClick={() => naviate('/detail')}>跳转详情页</button>
<Route path='/list/:id' element={<List />}></Route> // route/index.jsx
import { useParams } from 'react-router-dom' // List.jsx
const { id } = useParams() // List.jsx
<li><Link to="/home?id=456">首页</Link></li> // App.jsx
import { useSearchParams } from 'react-router-dom' // Home.jsx
const [searchParams] = useSearchParams()
console.log(searchParams.getAll('id')[0]);
const naviate = useNavigate()
const goDetail = () => {
naviate("/detail", {
state: { username: '张三' }
})
}
let location = useLocation()
console.log(location.state ? location.state.username : "");