# 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` 是返回一个函数, 通常用于子组件调用父组件方法的时候