5-React 组件通信 useEffect

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/54063a28-3a92-43d3-967e-eeff3cbb0f49.png)
## 一：父传子基础实现
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/4d8daf0d-f473-40b4-9c21-8eae273510b8.png)
1.父组件中通过给标签绑定一个属性，＝后面绑定传递的数据
2.子组件中设置props的参数，在参数中会包含着父组件传递过来的所有数据
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/f553312b-0552-4592-9c14-546a06a17759.png)
## 二：父传子props说明
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/09e47bcf-3449-4d30-a9a3-7a2585be821c.png)
## 三：父传子children说明
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/870d0194-0cb6-4d00-b0a0-6548f56a9991.png)
## 四：子传父实现
在子组件中调用父组件中的函数并传递实参
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/28ae6dbb-e7df-4910-b93f-810813f97d42.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/10a60292-a9db-48d0-8d91-5ab344b0f2b9.png)
## 五：使用状态提升实现兄弟组件通信
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/862a4205-112a-4343-86d1-cc167b166a34.png)
``` java
// 1.通过子传父 A-> App
// 2.通过父传子 App-> B

function A({onGetAName}){
  // Son组件中的数据
  const name = "this is A name"
  return (
     <div>
      this is A compnent,
      <button onClick= {()=>onGetAName(name)}>send</button>
      </div>
  )
}

function B({name}){
  return (
     <div>
      this is B compnent
      {name}
      </div>
  )
}

function App() {
  const [name, setName] = useState("")
  const getAName = (name) =>{
    console.log(name)
    setName(name)
  }
  return (
    <div>
      this is App
     <A onGetAName = {getAName}/>
     <B name={name}/>
    </div>
  )
}

export default App;
```
## 六：使用context机制跨层传递数据
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/aaac381f-55db-41e0-9fb1-3f7a4216ebc1.png)
```java
//App -> A -> B

import { useContext } from "react"

// 1.createContext方法创建一个上下文对象
const MsgContext = createContext()
// 2.在顶层组件 通过Provider组件提供数据

// 3.在顶层组件 通过useContext钩子函数使用数据

function A(){
  return (
     <div>
      this is A compnent,
      <B />
      </div>
  )
}

function B(){
  const msg = useContext(MsgContext)
  return (
     <div>
      this is B compnent,{msg}
      </div>
  )
}

function App() {
  const msg = "this is app msg"
  return (
    <div>
      <MsgContext.Provider value={msg}>
         this is App
         <A />
      </MsgContext.Provider>
    </div>
  )
}
export default App;
```
## 七：useEffect
#### 1.概念理解和基础使用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/4da1f31c-cf40-4244-9077-8ea59b74e8de.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/bdd4565c-7c59-4f36-aa0d-a9c14e37341f.png)
```java
import { useEffect, useState } from "react";

const URL = "  "
function App() {
  // 创建一个状态数据
  const [list,setList] = useState([])
  useEffect(()=>{
    // 额外的操作 获取频道列表
    async function getList(){
       const res = await fetch(URL)
       const jsonRes = await res.json()
       console.log(jsonRes)
       setList(jsonRes.data.channels)
    }
    getList()
  },[])
  return (
    <div>
         this is App
         <ul>
          {list.map(item => <li key={item.id}>{item.name}</li> )}
         </ul>
    </div>
  )
}
export default App;
```
#### 2.不同依赖项说明
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/24975cca-f5e2-4010-9f03-9f9ca5720fbc.png)
```java
import { useEffect, useState } from "react";

function App() {
  // 1.没有依赖项 初始＋组件更新
  const [count, setCount] = useState(0)
  useEffect(() =>{
    console.log("副作用函数执行了")
  })
  return (
    <div>
         this is App
         <button onClick ={()=>setCount(count +1)}>+{count}</button>
    </div>
  )
}
export default App;
```
```java
import { useEffect, useState } from "react";

function App() {
  // 2.传入空数组依赖  初始执行一次
  useEffect(()=>{
    console.log("副作用函数执行了")
  },[])
  return (
    <div>
         this is App
         <button onClick ={()=>setCount(count +1)}>+{count}</button>
    </div>
  )
}
export default App;
```
```java
import { useEffect, useState } from "react";

function App() {
  const [count,setCount] = useState(0)
  // 3.传入特定依赖项  初始 ＋ 依赖项变化时执行
  useEffect(()=>{
    console.log("副作用函数执行了")
  },[count])
  return (
    <div>
         this is App
         <button onClick ={()=>setCount(count +1)}>+{count}</button>
    </div>
  )
}
export default App;
```
#### 3.清除副作用
在第一个函数的末尾return一个新函数，在里面清除副作用
组件卸载时自动执行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/aff60c65-3d4b-4a83-839c-263f6f7e2ef7.png)
```java
import { useEffect, useState } from "react";

function Son(){
  // 1.渲染时开启一个定时器
  useEffect(()=>{
     const timer = setInterval(()=>{
      console.log("定时器执行中")
     },1000)

     return () =>{
      // 清除副作用 组件卸载时
      clearInterval(timer)
     }
  },[])
  return <div>this is son</div>
}

function App() {
  // 通过条件渲染模拟组件卸载
  const [show,setShow] = useState(true)
  return (
    <div>
         {show && <Son />}
         <button onClick ={()=>setShow(false)}>卸载Son组件</button>
    </div>
  )
}
export default App;
```
## 八：自定义hook实现
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/ce97f54e-ba12-4666-918e-dbda9b13d324.png)
```java
import { useEffect, useState } from "react";

// 封装自定义hook

// 1.声明一个以use打头的函数
// 2.在函数体内封装可复用的逻辑 只要是可复用的逻辑
// 3.把组件中用到的状态或者回调return出去 以对象或者数组
// 4.在哪个组件中要用到这个逻辑，就执行这个函数，解构出来状态和回调进行使用
function useToggle(){
  // 可复用的逻辑代码
  const [value,setValue] = useState(true)
  const toggle = ()=>setValue(!value)

  // 哪些状态和回调函数需要在其他组件中使用 return
  return{
    value,
    toggle
  }
}

function App() {
  const {value, toggle} = useToggle()
  return (
    <div>
        {value && <div>this is div</div>}
         <button onClick ={toggle}>toggle</button>
    </div>
  )
}
export default App;
```
## 九：reacthooks使用规则说明
#### 1.组件外使用
#### 2.if for组件内部函数
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/35688079-2818-47ce-9197-5704a5dd0c13.png)
## 十：案例优化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/1a3292d4-c952-454a-b7d8-ba459f1d2c29.png)
#### 1. 使用useEffect获取数据
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/c049b51f-9d7d-456e-823b-e852cdf46fcb.png)
①安装json-server
```java
npm i json-server -D
```
准备一个json文件，放到根目录下src-db.json
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/07b7d7b1-7657-42f4-ac74-1100258dc1e1.png)
创建命令，启动服务
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/60515529-6e34-4871-96c0-687377dfdd5e.png)
②安装Axios
```java
npm install axios
```
```java
// 获取接口数据渲染
const [commentList, setCommentList] = useState([])

useEffect(()=>{
// 请求数据
async  function getList(){
  // axios请求数据
  const res = await axios.get("http://localhost:3004/list")
  setCommentList(res.data)
  }
  getList()
},[])
```
#### 2. 自定义hook封装请求逻辑
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/d5982cb7-01a7-46b6-b481-e8104d8f902c.png)
```java
// 封装请求数据的hook
function useGetList(){
// 获取接口数据渲染
const [commentList, setCommentList] = useState([])

useEffect(()=>{
// 请求数据
async  function getList(){
  // axios请求数据
  const res = await axios.get("http://localhost:3004/list")
  setCommentList(res.data)
  }
  getList()
},[])
}

return {
  commentList,
  setCommentList
}

const {commentList,setCommentList} = useGetList()
```
#### 3. 评论item组件封装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/13bc0839-3ff2-4561-9b97-53e1304ed593.png)
```java
// 封装item组件
function Item({item}){
 return(
  <div key={item.rpid} className="reply-item">
  </div>
 )
}

// 原来评论项
{commentList.map(item => <Item key={item.id} item={item}/>)}
```