# react学习
**Repository Path**: weloves/react-learning
## Basic Information
- **Project Name**: react学习
- **Description**: 小白学习react
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-26
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## react 官方文档
https://zh-hans.reactjs.org/docs/handling-events.html
## ceact-react-app 文档
https://www.html.cn/create-react-app/docs/getting-started/
## redux 中文文档
https://www.redux.org.cn/
## react-redux 文档
https://www.redux.org.cn/docs/react-redux/
## react-router 中文文档
https://react-guide.github.io/react-router-cn/index.html
## setState 基本用法
1. 改变 state 里面的值如下:
```js
this.setState({
num: 1,
});
```
2. 可以是函数形式,如下
```js
this.setState((state) => ({
num: 1,
}));
```
3. 可以监听什么时候数据渲染完成,也就是说 setState 支持回调,如下
```js
this.setState(
{
num: 1,
},
() => {
console.log("我已经搞定了");
}
);
// 或者
this.setState(
(state) => ({
num: 1,
}),
() => {
console.log("我已经搞定了");
}
);
```
4. 和 vue 一样,setState 也是异步的,多个 setState 同时更新最后会合并
## react 复合组件 == vue 的插槽
react 的复合组件写法非常简单,下面我们定义一个 Layout 组件,并在其他组件中使用,并传递两个参数
```js
被包裹的组件
```
layout 中使用`this.prop`接受参数
```js
const { showHeader, showFooter, children } = this.prop;
// 使用数据
// xxx
{
children;
} // 被包裹的组件会被渲染到这里
// xxx
```
### 具名复合组件
把上面被包裹的组件在包裹一层即可
```js
{{
content: (
HomePage
),
txt: "这是个⽂本",
}}
```
Layout 中展示
```js
const { showHeader, showFooter, children } = this.prop;
// 使用数据
// xxx
{
children.content;
} // 被包裹的content组件会被渲染到这里
{
children.txt;
} // 被包裹的txt组件会被渲染到这里
// xxx
```
## redux 及 react-redux
这两个都可以用在 react 做状态管理,只不过 react-dedux 是对 redux 做了封装,使得在使用起来更加方便,而 redux 原则上可以用于任何的框架上
1. 使用方法, 这里我们存一个变量 state 及两个方法 add,del
```js
import { createStore } from "redux";
// 定义state初始化和修改规则
function counterReducer(state = 0, action) {
switch (action.type) {
case "ADD":
return state + 1;
case "DEL":
return state - 1;
default:
return state;
}
}
const store = createStore(counterReducer);
export default store;
```
2. 在组件中使用
```js
import store from "./store"; // 引入store
rander(
{store.getState()}
);
```
值得注意的是 redux 中跟新数据后并不会引起视图的变化,需要我们自己手动去更新视图
```js
componentDidMount(){
store.subscribe(()=>{
this.forceUpdate()
})
}
```
3. 同样的功能用 react-redux 写就可以省不少事
```js
import React, { Component } from "react";
import { connect } from "react-redux";
export default connect((state) => ({ num: state }))(
class ReactRedux extends Component {
render() {
const { num, dispatch } = this.props;
return (
{num}
);
}
}
);
```
我们还可以这样写
```js
import React, { Component } from "react";
import { connect } from "react-redux";
export default connect((state) => ({ num: state }), {
add: () => ({
type: "ADD",
}),
})(
class ReactRedux extends Component {
render() {
const { num, add } = this.props;
return (
{num}
);
}
}
);
```
我们还可以这样写
```js
import React, { Component } from "react";
import { connect } from "react-redux";
class ReactRedux extends Component {
render() {
const { num, add } = this.props;
return (
{num}
);
}
}
// 数据
const mapStateToProps = (state) => {
return {
num: state,
};
};
// 派发事件
const mapDispatchToProps = {
add: () => ({
type: "ADD",
}),
};
export default connect(mapStateToProps, mapDispatchToProps)(ReactRedux);
```
## react-router
比较好用,直接上代码
```js
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
export default class Routerpage extends Component {
render() {
return (
⾸首⻚页
⽤用户中⼼心
);
}
}
class HomePage extends Component {
render() {
return Home
;
}
}
class UserPage extends Component {
render() {
return User
;
}
}
class NoPage extends Component {
render() {
return 404
;
}
}
```
## Hook
不得不说 Hook 真像 vue3 中的 component-api 都是提供了一个逻辑复用的方案, 下面我们来看看在 React 中,Hook 是如何使用的把
1. useState
我的理解是命名一个响应式数据及改变它的方法,如:
```js
import React, { userState } from "react";
function Example() {
// 申明一个初始值为0的count
const [count, setCount] = useState(0);
return (
{count}
);
}
export default Example;
```
2. Effect
很好理解,页面数据改变时执行,官方称之为副作用,如下:
```js
import React, { userState, useEffect } from "react";
function Example() {
// 申明一个初始值为0的count
const [count, setCount] = useState(0);
useEffect(() => {
console.log("count数据改变喽");
// todo...
});
return (
{count}
);
}
export default Example;
```
值得注意的是 useEffect 可以设置为条件执行,也就是给他新增第二个参数,格式是数组,里面的内容是依赖项,当第二个参数是个空数组时,userEffect 就只会执行一次
```js
useEffect(() => {
console.log("count数据改变喽");
// todo...
}, [count]);
```
当这个组件卸载时,会执行 userEffect 中 return 出来的函数
> 为什么要在 effect 中返回一个函数? 这是 effect 可选的清除机制。每个 effect 都可以返回一个清除函数。如此可以将添加和移除订阅的逻辑放在一起。它们都属于 effect 的一部分。
> React 何时清除 effect? React 会在组件卸载的时候执行清除操作。正如之前学到的,effect 在每次渲染的时候都会执行。这就是为什么 React 会在执行当前 effect 之前对上一个 effect 进行清除。我们稍后将讨论为什么这将助于避免 bug 以及如何在遇到性能问题时跳过此行为。
```js
useEffect(() => {
console.log("count数据改变喽");
// todo...
return () => {
// 组件卸载时执行
};
}, [count]);
```
3. 自定义 Hook
也就是把公用的逻辑抽象成函数,只给外界返回函数处理结果
命名规则要以 `ues`开头,如:`useFriendStatus`
> 只在最顶层使用 Hook 不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。(如果你对此感到好奇,我们在下面会有更深入的解释。)
> 只在 React 函数中调用 Hook
3. Hook 中的计算属性 `useMemo`
接受两个参数,useMemo(fn,[]) 当数组中的数据发生改变时,函数就会重新执行,并返回计算后的结果,很像 vue 中的计算属性
4. 和`useMemo`十分相似的`useCallback`
不同点是`useCallback` 是返回一个函数,
通常用于子组件调用父组件方法的时候