接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的
的 value prop 决定。
新建useContext.js
函数组件,写入如下代码:
import React, { useEffect, useState, useContext } from 'react'
import axios from 'axios'
import '../css/middlecp.css'
const GlobalContext = React.createContext(); // 创建context对象
export default function UseContext() {
const [filmList, setFilmList] = useState([])
const [info, setInfo] = useState('')
useEffect(() => {
axios.get('/data.json').then(res => {
console.log(res.data.data.films)
setFilmList(res.data.data.films)
}, err => {
console.log(err)
})
}, [])
return (
<GlobalContext.Provider value={{
info: info,
changeInfo: (value) => {
setInfo(value)
}
}}>
<div>
{
filmList.map(item => {
return <FilmItem key={item.filmId} {...item}></FilmItem>
})
}
<FilmDetail></FilmDetail>
</div>
</GlobalContext.Provider>
)
}
function FilmItem(props) {
let { name, poster, grade, synopsis } = props
const value = useContext(GlobalContext)
console.log(value)
return <div className="filmitem" onClick={() => {
value.changeInfo(synopsis)
}}>
<img src={poster} alt={name}></img>
<h4>{name}</h4>
<div>观众评分:{grade}</div>
</div>
}
function FilmDetail() {
const value = useContext(GlobalContext)
return (
<div className="filmdetail">
{value.info}
</div>
)
}
可以看到在hooks
中,我们没有像类组件那样去套了层级,直接使用useContext
,可以看到效果跟类组件一样:
useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
新建useReducer.js
组件,写入代码:
import React, { useReducer } from 'react'
export default function UseReducer() {
// 处理函数
const reducer = (prevState, action) => {
console.log(prevState, action)
let newState = {...prevState}
switch(action.type) {
case 'minus':
newState.count--
return newState;
case 'add':
newState.count++
return newState;
default:
return newState;
}
}
// 外部对象
const intialState = {
count: 0
}
const [state, dispatch] = useReducer(reducer, intialState)
return (
<div>
<button onClick={() => {
dispatch({
type: "minus"
})
}}>-</button>
{state.count}
<button onClick={() => {
dispatch({
type: "add"
})
}}>+</button>
</div>
)
}
hooks中useContext搭配useReducer使用跨级通信。(hooks中自带的,后面redux不用这么麻烦)
修改useReducer.js
组件代码为如下:
import React, { useReducer, useContext } from 'react'
// 处理函数
const reducer = (prevState, action) => {
console.log(prevState, action)
let newState = {...prevState}
switch(action.type) {
case 'child2':
newState.a = '改变后的a'
return newState;
case 'child3':
newState.b = '改变后的b'
return newState;
default:
return newState;
}
}
// 外部对象
const intialState = {
a: 'aaaaa',
b: 'bbbbb'
}
const GlobalContext = React.createContext()
export default function UseReducer() {
const [state, dispatch] = useReducer(reducer, intialState)
return (
<GlobalContext.Provider value={
{
state,
dispatch
}
}>
<div>
<Child1></Child1>
<Child2></Child2>
<Child3></Child3>
</div>
</GlobalContext.Provider>
)
}
function Child1() {
const {dispatch} = useContext(GlobalContext)
return (
<div>
<button onClick={() => {
dispatch({
type: 'child2'
})
}}>改变child2</button>
<button onClick={() => {
dispatch({
type: 'child3'
})
}}>改变child3</button>
</div>
)
}
function Child2() {
const {state} = useContext(GlobalContext)
return (
<div>
{state.a}
</div>
)
}
function Child3() {
const {state} = useContext(GlobalContext)
return (
<div>
{state.b}
</div>
)
}
当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。
必须使用use
开头。(实际上就是将独立的逻辑函数抽离出来封装)
新建useCustom.js
,写入代码:
import React, { useEffect, useMemo, useState } from 'react'
import axios from 'axios'
function useCinemaList() {
const [cinemaList, setCinemaList] = useState([])
useEffect(() => {
axios({
url: 'https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=3085018',
method: 'get',
headers: {
'X-Client-Info':' {"a":"3000","ch":"1002","v":"5.2.0","e":"1646314068530784943341569"}',
'X-Host': 'mall.film-ticket.cinema.list'
}
}).then((res) => {
console.log(res.data)
setCinemaList(res.data.data.cinemas)
}).catch((err) => {
console.log(err)
})
},[])
return {
cinemaList
}
}
function useFliter(cinemaList, text) {
const getCinemaList = useMemo(() => cinemaList.filter(item => item.name.toUpperCase().includes(text.toUpperCase()) ||
item.address.toUpperCase().includes(text.toUpperCase())), [cinemaList, text]) // useMemo会执行函数并返回执行后的结果
return {
getCinemaList
}
}
export default function UseCustom() {
const [text, setText] = useState('')
const {cinemaList} = useCinemaList()
const {getCinemaList} = useFliter(cinemaList, text)
return (
<div>
<input value={text} onChange={(event) => {
setText(event.target.value)
}}></input>
{
getCinemaList.map((item) =>
<dl key={item.cinemaId}>
<dt>{item.name}</dt>
<dd>{item.address}</dd>
</dl>
)
}
</div>
)
}
效果:
可以看到我们这个影院的筛选功能还是正常,但是看代码的话,逻辑更加的清晰了。
在学习React的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。