是我暂时的一些理解
并未长时间使用react 如果你是react大神 下面的可以不看了
如果是vue使用者 想了解react 看懂react的代码的同学可以看看
React.createContext
这个有点类似vue的provide 与inject 有一定的穿透的能力 小范围的数据
使用它有两种方式
第一种是配合 Provider Consumer
const {Provider, Consumer} = React.createContext(defaultValue);
一个是传值的属性,一个是接收值得属性
这个接收值暂时我看到是在组件上接收的
还有第二种接收的方式 useContent
这个API 可以直接帮我们获得上层组件定义的createContext
我更偏向于这个 好记 与usestate使用很类似
const { state,dispatch } = useContext(ReduceContext);
本质使用上暂时觉得和usestate 没有什么大的区别 这俩的使用场景 也基本一致
所以看到 useContext 就想他就是“useState”就可以啦 也是数据的处理一种
useRef() 类似于vue的ref
对于redux
首先分为两种 以及三个基础的概念
基础概念 都只有一个store
action是一个函数 但是类似于一个参数告诉更改那个state
reducer 用来更改的那个函数的具体执行 用来更改state
第一个是我看到的一个源码的store 已经被弃用了
const store = createStore(
combineReducers({
...commonStore,
}),
applyMiddleware(thunk, logger)
);
他们只有一个store 暂时我知道是可以store.getState()这种方式来获得
官网示例是第二种 也推荐第二种
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
简单说 就是现在的redux 都使用reduxjs/toolkit的方式创建了
使用state的时候也很简单
使用API
const selectCount = (state) => state.counter.value
const count = useSelector(selectCount);
或者 const count = useSelector(()=>state.**.***);
这是创建了store 但是 还要创建 action 和reducers
export const counterSlice = createSlice({
name: 'counter11',
initialState,
// The `reducers` field lets us define reducers and generate associated actions
reducers: {
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
extraReducers: (builder) => {
builder
.addCase(incrementAsync.pending, (state) => {
state.status = 'loading';
})
.addCase(incrementAsync.fulfilled, (state, action) => {
state.status = 'idle';
state.value += action.payload;
});
},
});
这里有两个比较重要的事 一个是initState 声明好 这里是{value,:0,attr:**}
所以就是state.conter.value了
另一个就是reducers 这个api 会将reducers自动的生成对应的actions
使用的时候 可以
counterSlice.actions.incrementByAmount
也可以export {incrementByAmount} = counterSlice.actions
然后
const dispatch = useDispatch();
dispatch(incrementByAmount(值))
就可以了
这里有一个是异步的reducers的特殊处理
要用
createAsyncThunk这个API
然后在createSlice 的extraReducers 里面将请求得到的结果返回
如果需要全面的学习一下 建议
用这个示例的counter 学习一下
react
React.createContext
这个是用来穿透属性的传递的 具体有没有响应式我还没测试 只是穿透属性 没有响应式 需要将setState 方法传过去 调用set方法 来实现响应
用法
这个声明
const ThemeContext = React.createContext('light')
const {Provider, Consumer} = React.createContext(defaultValue);
Provider 是赋值的 需要声明value 是什么
consumer是接收值得
也可以配合useContent使用直接获得变量
总结 小范围的context useReducer (可以理解为useState)
大范围redux
setState 是异步还是同步
要看他是否进入react的调度了 大白话就是在异步函数中就是同步的 在同步函数中就是异步的
组件要加一个类属性 propTypes
Input defaultvalue 可以设置初始化 直接value 回导致变成受控组件 咋不能更改了
context使用
Provider 生产者 供应商
第一步
Const glob =react.createContext
使用 glob.provider 包上父组件 父组件内部的子组件才可以使用content
子组件需要用
Glob.customer 包上 并且 里面是个 回调函数
export const Glob = React.createContext();
export function App(props) {
return (
<Glob.Provider value={{ name: "王洋" }}>
<div className="App">
<Con1></Con1>
<Con2></Con2>
</div>
</Glob.Provider>
);
}
使用
import { Glob } from "../App";
export default function Con11(params) {
return (
<Glob.Consumer>
{(value) => {
console.log(value);
return <div>nihao </div>;
}}
</Glob.Consumer>
);
}
如果想可以通过改变 控制显示 可以将value 的某个值设置为state的值
再将一个value的值设置为 setState的函数
总结:不能直接修改context的值 不过可以使用他的值 进而去做一些事 比如修改值(调用修改值得函数来修改 这个函数也是他的一个值)
插槽
就是用一个children属性
import React ,{Component} from 'react'
class Con2 extends Component{
constructor(){
super()
}
render(){
return <div>黑呵呵哈哈哈
{this.props.children}
</div>
}
}
export default Con2
插槽 一一对应位置的话 最外层的div 就是一个个数组 下标选择即可
{this.props.children[0]}
useEffect
useEffect(()=>{},[])只会执行一次
数组有值的话 就是根据值变化 执行一次
不传值 组件的初始化和更新都会执行
Usecallback
setstate会导致整个组件的渲染重新渲染
usestate本身就是一个记忆函数组件 (setstate 会导致重新渲染 但是值没有重置 是因为他被记住了 类似于使用了usecallback 记忆住 缓存了)
这里需要特别注意的是
如果使用usecallback 会缓存函数 如果传的是空数组 那么里面的变量 使用的state 都是最开始的 不会变化
为了解决这一问题 需要在数组里面写上 用到的变量 就会重新的创建一下这个函数 使用最新的state 和变量啦
Usememo 会把第一个参数执行
所以要将函数作为结果返回给第一个参数 usememo(()=>fn,[]) 使用场景 vue的计算属性
Usecallback 的值是一个函数 usememo 是一个值 可能是函数 也可以是具体的值 computed
Useref 的cuurent 本身也会有值的缓存
useContext 可以让消费者glob.customer的使用更方便
Const a=useContext(glob)
useReducer 一般会与usecontext使用
数据处理函数
Const reducer=(old,action)=>{
Action.type==****
必须不操作原状态
用一个新对象 得到原状态
必须返回一个新状态
}
Const init={
Count:0
}
Const [state,dispath]=useReducer(reducer,init)
()=>{
Dispatch({
Type:'aaa'})
}
Const glob=react.createContext
Const [state,dispatch] =useReducer(reducer,initobj)
<glob.provider value={state,dispatch}></>
在子组件中用useContext 接受这两个 就可以了 然后就可以使用state 与dispatch
自定义hooks
命名以use就可以了
Function useMuhoooks(){
Const [state,setstate]= usestate()
Return {
Count}
}
函数式组件内 ()=>{
Const {count}=useMyhooks()
}
React 路由
根据不用的url显示不同的页面组件
安装 npm I react-router-dom
《hashrouter》
<route>
<Rediret from =" " to="" 重定向 从哪跳到那
需要注意的是 在react 中/ 是万能匹配路由 所有的地址 都会走这个重定向
为了解决这个问题
引用switch 类似siwtch 语句 匹配到谁 就不匹配下一个了
<hashRouter>
< switach>
<route>
<route>
<rediret>
<siwtch>
<hashroute>
重定向的精确匹配
《Redirect from =" " to="" exact》
特别注意 不加这个属性都会是模糊匹配 二级路由 或者和名字差不多的 就会匹配到第一个了
也可以不写path 这样 当前面的都不匹配的时候就会走这个 所有的 都会走没有path的这个route
嵌套路由
就是在路由的组件中 在需要显示的位置 写上
<route path="" component=""> 在组件中再写一遍这个
需要注意的是 这样就不可以使用模糊匹配了 不然的话 就走不到嵌套路由了
要先走到第一层的路由 才可以到嵌套路由
使用重定向 一样
编程式 与声明式
编程式 就是 js 跳转 声明式 就是写在标签里面的 类似于vue的 routelink
<a href="#/films"> 注意这是#号开始的
//可以更改显示的高亮样式
<navlink to="/" activeClassname=""></>
可以带一个id 的
<navlink to="/***/id" activeClassname=""></>
编程式
Window.href="#/***"
Props.histoory.push("/***/***(id)")
Impoort { useHistory} from 'react-router-dom
Const history =useHistory()
Histtory.push()
动态路由
就是在路径上加一个 :**
<Route component path=“/ddd/:customId” >
然后在参数props 中的params可以拿到值 customId
与vue 一样 也有编程式跳转传参
This.props.history.push({pathname:'/***',query:{day:***}})
路由拦截
<Route path="/home" render={()=></Home>}
进而
<Route path="/home" render={()=>if(是否授权)=>{
Return </Home>}else{
Return </Login>}}
这种写法的话props是空的
所以需要在render 的参数props 得到并且传递下去
<Route path="/home" render={(props)=>if(是否授权)=>{
Return </Home {…props}>}else{
Return </Login>}}
Withrouter 的使用 让组件自己有props 可以跳转
Function zizujian (){}
Const aaa=widthRouter(zizujian)
<aaa> 这个组件 就可以得到props了
反向代理
Npm I http.proxy.middleware
SRC 目录下 新建 setupproxy.js
需要注意的事 与vue 不同的事 这是在前面加了什么地址 vue 是替换了 字段
Module.exports=function(){
App.use()
多个 就多个
APP.use()
}
Cssmodule
***.module.css
Import style from '****.module.css'
activeclassName={style.aa}