React入门第二篇

感觉自己啥也不会,啊啊啊啊啊啊(发个癫)

受控表单绑定

基本概念

使用React组件的状态控制表单的状态

image-20260208175554332

代码实现

 import { useState } from 'react';
 ​
 function MyForm() {
   const [inputValue, setInputValue] = useState("");
 ​
   return (
     <input
       type="text"
       value={inputValue}
       onChange={(e) => setInputValue(e.target.value)}
     />
  );
 }

获取DOM

使用userRef钩子函数生成一个ref对象,然后绑定到dom标签上,在dom可用时,用current方法获取dom

代码实现

 import {useRef} from "react"
 ​
 function List(){
   const inputRef = useRef(null)
   const showDom = () => {
     console.dir(inputRef.current)
  }
   return(
     <div>
       <input type="text" ref={inputRef} />
       <button onClick={showDom}>获取DOM</button>
     </div>
  )
 }
 export default List

组件通信

组件通信就是组件之间传递数据,根据组件嵌套关系不同,有不同的通信方法。

父子通讯

父传子

在子组件标签上绑定属性,子组件通过props参数接收数据。

代码实现

 function Content(props){
   console.log(props)
   return <div>play Delta Force</div>
 }
 ​
 function List(){
   const detail = 'welcome to'
   return(
     <div>
       <Content detail={detail}></Content>
     </div>
  )
 }
 export default List

props是一个对象,包含了父组件传递过来的所有数据。

image-20260208184008326

props可以传递任何类型的数据,可以是数字对象,字符串,也可以是对象函数,JSX。但是子组件只能读取props中的数据,并不能直接修改,父组件的数据只能由父组件修改。

       <Content 
         detail={detail}
         age={18}
         isTrue={false}
         list={['vue','react']}
         obj={{name: 'ttdr'}}
         cd={() => console.log('ttdr')}
         child ={<div>this is jsx</div>}
       ></Content>

这么多类型都可以。

父传子特殊的prop children

当我们把内容嵌套在子组件中,父组件ui自动在名为children的prop的属性中接收该内容。

such as

 <Content><div>Star Railway</div></Content>

我们也只需要用{prop.children}在子组件里面渲染

子传父

在子组件中调用父组件中的函数并且传递参数。

 import {useRef} from "react"
 ​
 function Content(props){
   const sonMsg = 'this is msg'
   return(
   <button onClick={() => props.onGetmsg(sonMsg)}>click</button>
  )
 }
 ​
 function List(){
   const [msg,setMsg] = useState('')
   const getMsg =(msg) =>{
     console.log(msg)
     setMsg(msg)
  }
   return(
     <div>
      {msg}
       <Content
         onGetmsg ={getMsg}
       ></Content>
     </div>
  )
 }
 export default List

兄弟组件通信

借助状态提升机制,通过共同的父组件进行兄弟组件之间的提升

说白了就是子传父再传子。

Context实现跨层通讯

通过createContext方法创建一个上下文对象,顶层组件通过Ctx.Provider组件提供数据,底层通过useContext钩子函数获取使用数据

 import {createContext, useContext, useRef} from "react"
 ​
 const MsgContext = createContext()
 ​
 function B(){
   const message  = useContext(MsgContext)
   return (
     <div>this is b {message}</div>
  )
 }
 ​
 function A(){
   return(
     <>
     <div>this is a</div>
     <B />
     </>
  )
 }
 ​
 function List(){
   const message ='this is message'
   return(
     <div>
       <MsgContext.Provider value={message}>
        this is top
         <A />
       </MsgContext.Provider>
     </div>
 ​
  )
 }
 export default List

value就是要传输的值

useEffect

这是一个Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作,入AJAX请求,更改DOM等等

比如说一个模块渲染完毕,就向服务器请求数据。

语法:

 useEffect(() => {},[])

第一个参数是函数,称为副作用函数,在函数内部可以放置需要执行的操作

第二个参数是数组,在数字内放置依赖项,不同依赖项会影响第一个参数函数的执行,如果是空数组副作用函数只会在渲染完毕后执行一次

 import { useEffect, useState } from 'react'
 ​
 function App() {
   useEffect(() => {
     async function loadData() {
       // 发送请求...
       console.log('组件渲染完毕,只执行一次')
    }
     loadData()
  }, [])
 ​
   return <div>App</div>
 }

如果不是空数组,组件初始渲染执行一次 + 当数组内的依赖项发生变化时执行一次

 import { useEffect, useState } from 'react'
 ​
 function App() {
   const [count, setCount] = useState(0)
   useEffect(() => {
     console.log('count 发生了变化:', count)
     document.title = `当前点击了 ${count} 次`
  }, [count])
 ​
   return (
     <button onClick={() => setCount(count + 1)}>+1</button>
  )
 }

清除副作用

useEffect 中,如果开启了定时器、订阅了事件或建立了 socket 连接,需要在组件卸载(Unmount)或依赖项变化重新执行副作用前进行清理,防止内存泄漏。

在副作用函数内部 return 一个新的函数,这个函数就是清理函数

 import { useEffect, useState } from 'react'
 ​
 function Timer() {
   useEffect(() => {
     const timerId = setInterval(() => {
       console.log('定时器执行中')
    }, 1000)
     return () => {
       clearInterval(timerId)
       console.log('已清理')
    }
  }, [])
 ​
   return <div>Timer Running...</div>
 }
 ​
 function App() {
   const [show, setShow] = useState(true)
   return (
     <div>
      {show && <Timer />}
       <button onClick={() => setShow(!show)}>切换显示/隐藏</button>
     </div>
  )
 }

自定义 Hook 实现

以use打头的函数,实现逻辑的封装和复用

 import { useState } from 'react'
 ​
 function useToggle() {
   const [value, setValue] = useState(true)
   const toggle = () => setValue(!value)
   return {
     value,
     toggle
  }
 }
 ​
 function App() {
   const { value, toggle } = useToggle()
 ​
   return (
     <div>
      {value && <div>This is a Div</div>}
       <button onClick={toggle}>Toggle</button>
     </div>
  )
 }

注意事项

1.只能在函数组件的最顶层调用

禁止在循环(if/for)、条件判断或嵌套函数中调用 Hook,React 依靠 Hook 调用的顺序来确定每个 state 对应哪个 Hook,打乱顺序会导致数据错乱。

2.只能在 React 函数组件或自定义 Hook 中调用

禁止在普通的 JavaScript 函数中调用 Hook。

暂无评论

发送评论 编辑评论


				
上一篇
下一篇