React二组件进阶

代码下载

React 组件通讯

组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据。在组件化过程中,我们将一个完整的功能

拆分成多个组件,以更好的完成整个应用的功能。而在这个过程中,多个组件之间不可避免的要共享某些数据

。为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通。这个过程就是组件通讯。

组件的 props

组件是封闭的,要接收外部数据应该通过 props 来实现:

  • props的作用是接收传递给组件的数据

  • 传递数据通过给组件标签添加属性

  • 接收数据,函数组件通过参数props接收数据,类组件通过 this.props 接收数据

    // 接收参数
    function FuncProps(props) {
    return (


    函数组件 props


    姓名:{props.name},年龄:{props.age}



    )
    }
    // 传递参数
    ReactDOM.createRoot(document.getElementById('funcProps')).render(<FuncProps name='张三' age='18'></FuncProps>)

    class ClassProps extends React.Component {
    constructor(props) {
    super()
    console.log(props);
    }
    render() {
    return (


    类组件 props


    姓名:{this.props.name},年龄:{this.props.age}



    )
    }
    }
    ReactDOM.createRoot(document.getElementById('classProps')).render(<ClassProps name='李四' age='19'></ClassProps>)

props 的特点:

  • 可以给组件传递任意类型的数据

  • props 是只读的对象,只能读取属性的值,无法修改对象

  • 使用类组件时,如果写了构造函数,应该将 props 作为构造函数的参数,并推荐将 props 传递给 super(),否则无法在构造函数中获取到 props

    class PropsParticular extends React.Component {
    constructor(props) {
    // 推荐将props传递给父类构造函数
    super(props)
    console.log(props);
    }

    changeProps = () => {
      this.props.str = 'string'
    }
    render() {
      return (
        <div>
          <h4>props 的特点</h4>
          <p>字符串:{this.props.str},数值:{this.props.num},对象:{JSON.stringify(this.props.obj)}</p>
          {this.props.label}
          <button onClick={this.props.func}>函数</button>
          <button onClick={this.changeProps}>修改 props</button>
        </div>
      )
    }
    

    }
    ReactDOM.createRoot(document.getElementById('propsParticular')).render(<PropsParticular
    str='我是字符串'
    num={19}
    obj={{ a: 'a', b: 'b'}}
    label={

    我是标签

    }
    func={() => alert('我是函数')}

    </PropsParticular>)

组件通讯的三种方式

1、父组件传递数据给子组件:

  • 父组件提供要传递的state数据

  • 给子组件标签添加属性,值为 state 中的数据

  • 子组件中通过 props 接收父组件中传递的数据

    class Parent extends React.Component {
    state = {
    lastName: '张'
    }
    render() {
    return (


    父组件传递数据给子组件


    父组件:我姓{this.state.lastName}

    <Son lastName={this.state.lastName}></Son>

    )
    }
    }
    class Son extends React.Component {
    render() {
    return
    子组件:我爸爸姓{this.props.lastName}所以我姓{this.props.lastName}

    }
    }
    ReactDOM.createRoot(document.getElementById('parentToSon')).render(<Parent></Parent>)

2、子组件传递数据给父组件,思路是利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数:

  • 父组件提供一个回调函数(用于接收数据),将该函数作为属性的值,传递给子组件

  • 子组件通过 props 调用回调函数,将子组件的数据作为参数传递给回调函数

    class ParentOne extends React.Component {
    state = { sonMsg: '' }
    message = msg => {
    this.setState({ sonMsg: msg })
    console.log('state: ', this.state);
    }
    render() {
    return (


    子组件传递数据给父组件


    父组件:{this.state.sonMsg.length > 0 ? '我儿子在' + this.state.sonMsg : ''}

    <SonOne sendMsg={this.message}></SonOne>

    )
    }
    }
    class SonOne extends React.Component {
    render() {
    return (
    子组件:发消息
    <button onClick={() => this.props.sendMsg('打球')}>打球</button>
    <button onClick={() => this.props.sendMsg('打游戏')}>打游戏</button>
    <button onClick={() => this.props.sendMsg('写作业')}>写作业</button>

    )
    }
    }
    ReactDOM.createRoot(document.getElementById('sonToParent')).render(<ParentOne></ParentOne>)

3、兄弟组件传递数据:

将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态

  • 思想:状态提升

  • 公共父组件职责:1. 提供共享状态 2. 提供操作共享状态的方法

  • 要通讯的子组件只需通过 props 接收状态或操作状态的方法

    class ParentTwo extends React.Component {
    state = {
    count: 0
    }
    changeCount = (value) => {
    this.setState({ count: value + this.state.count })
    }
    render() {
    return (


    兄弟组件传递数据


    <SonTwo count={this.state.count}></SonTwo>
    <SonThree changeCount={this.changeCount}></SonThree>

    )
    }
    }
    class SonTwo extends React.Component {
    render() { return

    结果:{this.props.count}

    }
    }
    class SonThree extends React.Component {
    render() { return <button onClick={() => { this.props.changeCount(1) }}>+1</button> }
    }
    ReactDOM.createRoot(document.getElementById('brotherToBrother')).render(<ParentTwo></ParentTwo>)

Context

Context 的作用是跨组件传递数据,如果出现层级比较多的情况下(例如:爷爷传递数据给孙子),会使用Context来进行传递,使用步骤如下:

  • 调用 React.createContext() 创建 Provider(提供数据) 和 Consumer(消费数据) 两个组件

  • 使用Provider 组件作为父节点

  • 设置value属性,表示要传递的数据

  • 哪一层想要接收数据,就用Consumer进行包裹,在里面回调函数中的参数就是传递过来的值

    const { Provider, Consumer } = React.createContext()
    class ContextParent extends React.Component {
    render() {
    return (
    <Provider value={{ name: '张三', age: 18 }}>
    <div style={{padding: 10, width: 200, height: 100, backgroundColor: 'red', boxSizing: 'border-box'}}>
    <ContextNode></ContextNode>


</Provider>
)
}
}
const ContextNode = () => {
return (
<div style={{ padding: 10, width: 180, height: 80, backgroundColor: 'green', boxSizing: 'border-box'}}>
<ContextSubNode></ContextSubNode>

)
}
const ContextSubNode = () => {
return (
<div style={{ padding: 10, width: 160, height: 60, backgroundColor: 'blue', boxSizing: 'border-box'}}>
<ContextChild></ContextChild>

)
}
const ContextChild = () => {
return (
<Consumer>
{ (data) => (<div style={{ width: 140, height: 40, backgroundColor: 'cyan'}}>{'我是' + data.name + ',' + data.age + '岁'}
) }
</Consumer>
)
}
ReactDOM.createRoot(document.getElementById('contextParent')).render(<ContextParent></ContextParent>)

props 进阶

children 属性

children 属性表示组件标签的子节点。当组件标签有子节点时,props 就会有该属性。children 属性与普通的props一样,值可以是任意值(文本、React元素、组件,甚至是函数)。

const ChildrenCom = (props) => (<>{props.children}</>)
const jsx = (<><p>JSX</p></>)
const TestCom = () => (<>组件</>)
const FuncChildren = (props) => (<div><button onClick={props.children}>函数</button></div>)
class ChildrenProp extends React.Component {
  render() {
    return (
      <>
        <h4>children 属性</h4>
        <ChildrenCom>文本节点</ChildrenCom>
        <ChildrenCom><p>p 标签</p></ChildrenCom>
        <ChildrenCom>{jsx}</ChildrenCom>
        <ChildrenCom><TestCom></TestCom></ChildrenCom>
        <FuncChildren>{() => alert('函数 children')}</FuncChildren>
      </>
    )
  }
}
ReactDOM.createRoot(document.getElementById('childrenProp')).render(<ChildrenProp></ChildrenProp>)
props 校验

对于组件来说,props 是外来的,无法保证组件使用者传入什么格式的数据。如果传入的数据格式不对,可能会导致组件内部报错

关键问题:组件的使用者不知道明确的错误原因

props 校验允许在创建组件的时候,就指定 props 的类型、格式等。捕获使用组件时因为 props 导致的错误,给出明确的错误提示,增加组件的健壮性。使用步骤如下:

  • 安装包 prop-types (yarn add prop-types / npm i props-types)

  • 导入 prop-types 包 import PropTypes from 'prop-types'

  • 使用 组件名.propTypes = {} 来给组件的props添加校验规则

  • 校验规则通过 PropTypes 对象来指定

    import PropTypes from 'prop-types'
    const PropsCheck = (props) => {
    return (
    <>

    props 校验


    {/*
      {props.colors.map((item, i) => (
    • {item}
    • ))}
    /}
    {/
    <button onClick={props.func}>报错</button> */}

    {'intValue: ' + props.intValue}


    ......
    </>
    )
    }
    // 添加校验
    PropsCheck.propTypes = {
    intValue: PropTypes.number,
    stringValue: PropTypes.string.isRequired,
    elementValue: PropTypes.element,
    arrayValue: PropTypes.array,
    objectValue: PropTypes.shape({
    name: PropTypes.string.isRequired,
    age: PropTypes.number
    }).isRequired,
    funcValue: PropTypes.func
    }
    const checkCom = <PropsCheck
    intValue='a'
    funcValue='a'

    </PropsCheck>

    ReactDOM.createRoot(document.getElementById('propsCheck')).render(checkCom)

常见的约束规则:

  • 常见的类型: array、bool、func、number、object、string
  • React元素类型:element
  • 必填项:isRequired
  • 特定结构的对象: shape({})
  • 更多的约束规则
props 的默认值

可以给 props 设置默认值,在未传入 props 时生效,函数组件和类组件有所不同。

1、函数组件

  • 方法一:通过在参数后面写 = 和默认值来进行解构

  • 方法二:使用 组件名.propTypes = {},此方法以后将在函数组件中移除不推荐使用。

    // 函数组件 props 默认值
    // 方法一
    const FuncPropsDefault = ({age=18, ...props}) => {
    console.log('props: ', props);
    return (
    <>

    {props: ${JSON.stringify(props)}, age: ${age}}
    </>
    )
    }
    // 方法二 此方法将移除,不推荐使用
    FuncPropsDefault.defaultProps = {
    name: '张三'
    }

2、类组件

  • 方法一:在类组件的定义中使用 static defaultProps = {},定义静态属性。

  • 方法二:与函数组件一样使用 组件名.propTypes = {}

    // 类组件 props 默认值
    class ClassPropsDefaultOne extends React.Component {
    // 方法一
    static defaultProps = {
    name: '李四',
    age: 19
    }
    render = () => <>

    {JSON.stringify(this.props)}
    </>
    }
    // 方法二
    class ClassPropsDefaultTwo extends React.Component {
    render = () => <>
    {JSON.stringify(this.props)}
    </>
    }
    ClassPropsDefaultTwo.defaultProps = {
    name: '王五',
    age: 20
    }

组件的生命周期

组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因等。组件的生命周期包含组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程。

生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数。钩子函数的作用是为开发人员在不同阶段操作组件提供了时机。

只有 类组件 才有生命周期。

1、创建时(挂载阶段),执行时机是组件创建时(页面加载时),执行顺序 constructor() -> render() -> componentDidMount()

钩子函数 触发时机 作用
constructor 创建组件时,最先执行 初始化state、为事件处理程序绑定this......
render 每次组件渲染都会触发 渲染UI(注意:不能调用setState())
componentDidMount 组件挂载(完成DOM渲染)后 发送网络请求、DOM操作

2、更新时(更新阶段),执行时机:

  • setState()
  • forceUpdate()
  • 组件接收到新的props

以上三者任意一种变化,组件就会重新渲染,执行顺序:render() -> componentDidUpdate()

钩子函数 触发时机 作用
render 每次组件渲染都会触发 渲染UI(与 挂在阶段 是同一个render)
componentDidUpdate 组件更新(完成DOM渲染)后 发送网络请求、DOM操作......,注意:如果要setState() 必须放在一个if条件中

3、卸载时(卸载阶段), 执行时机是组件从页面中消失。

钩子函数 触发时机 作用
componentWillUnmount 组件卸载(从页面中消失) 执行清理工作(比如:清理定时器等)
class LifeCircle extends React.Component {
  // 生命周期
  constructor() {
    super()

    // 初始化state
    this.state = { count: 0 }
    // 处理 this 指向问题......

    console.warn('生命周期钩子函数: constructor');
  }
  componentDidMount() {
    // 可以在这里 请求网络、操作 DOM
    console.warn('生命周期钩子函数: componentDidMount');
  }
  shouldComponentUpdate() {
    console.warn('生命周期钩子函数: shouldComponentUpdate')
    return true
  }
  render() { 
    // 不能 更新状态
    console.warn('生命周期钩子函数: render');
    return (
      <>
        {this.state.count > 3 ? <p>豆豆被打死了</p> : <Counter count={this.state.count}></Counter>}
        <button onClick={() => this.forceUpdate()}>强制刷新</button>
        <button onClick={this.clickHandle}>打豆豆</button>
      </>
    ) 
  }
  componentDidUpdate(prevProps) {
    // 可以在这里 请求网络、操作 DOM,但是需要注意,若果 setState() 必须放在一个条件语句中,否则容易导致死循环
    // 一般来说判断状态是否变化
    if (prevProps.count !== this.props.count) {
      // this.setState({ count: this.state.count})
      // 网络请求......
    }
    console.warn('生命周期钩子函数: componentDidUpdate');
  }
  componentWillUnmount() {
    // 执行清理工作(比如:清理定时器等)
    console.warn('生命周期钩子函数: componentWillUnmount')
  }
  getSnapshotBeforeUpdate() {
    console.warn('生命周期钩子函数: getSnapshotBeforeUpdate')
    return null
  }
  
  clickHandle = () => {
    this.setState({ count: this.state.count + 1 })
  }
}
class Counter extends React.Component {
  constructor() {
    super()
    console.warn('--子组件--生命周期钩子函数: constructor')
  }
  componentDidMount() {
    console.warn('--子组件--生命周期钩子函数: componentDidMount')
    this.timerOne = setInterval(() => {
      console.log('timer one');
    }, 1000);
    this.timerTwo = setInterval(() => {
      console.log('timer two');
    }, 3000);
  }
  shouldComponentUpdate() {
    console.warn('--子组件--生命周期钩子函数: shouldComponentUpdate')
    return true
  }
  render() {
    console.warn('--子组件--生命周期钩子函数: render')
    return (<p>统计豆豆被打的次数:{this.props.count}</p>)
  }
  componentDidUpdate() {
    console.warn('--子组件--生命周期钩子函数: componentDidUpdate')
  }
  componentWillUnmount() {
    // 执行清理工作(比如:清理定时器等)
    clearInterval(this.timerOne)
    console.warn('--子组件--生命周期钩子函数: componentWillUnmount')
  }
  getSnapshotBeforeUpdate() {
    console.warn('--子组件--生命周期钩子函数: getSnapshotBeforeUpdate')
    return null
  }
}
ReactDOM.createRoot(document.getElementById('lifeCircle')).render(<LifeCircle></LifeCircle>)
完整生命周期钩子函数

getDerivedStateFromProps()

  • getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容
  • 不管原因是什么,都会在每次渲染前触发此方法
  • 已经弃用

shouldComponentUpdate()

  • 根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染
  • 当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true

getSnapshotBeforeUpdate()

  • getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()
  • 此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等

render-props和高阶组件

思考:如果两个组件中的部分功能相似或相同,该如何处理?

复用相似的功能(联想函数封装),复用什么? 复用的就是 state 和 操作state的方法 (组件状态逻辑 )。两种方式:

  • render props模式
  • 高阶组件(HOC)

这两种方式不是新的API,而是利用React自身特点的编码技巧,演化而成的固定模式(写法)。

render props 模式

将要复用的state和操作state的方法封装到一个组件中,那么就涉及两个问题:

  1. 如何拿到该组件中复用的state?在使用组件时,添加一个值为函数的prop,通过 函数参数 来获取(需要组件内部实现)

  2. 如何渲染任意的UI?使用该函数的返回值作为要渲染的UI内容(需要组件内部实现)

    <Mouse render={(point) => { return

    鼠标位置:{point.x}, {point.y}

    }}></Mouse>

使用步骤:

  • 创建Mouse组件,在组件中提供复用的状态逻辑代码(1. 状态 2. 操作状态的方法)

  • 将要复用的状态作为 props.render(state) 方法的参数,暴露到组件外部

  • 使用 props.render() 的返回值作为要渲染的内容

    class Mouse extends React.Component {
    state = { x: 0, y: 0 }
    render() { return this.props.render(this.state) }
    // 监听鼠标
    componentDidMount() {
    window.addEventListener('mousemove', this.mouseMoveHandle)
    }

    // 鼠标移动处理
    mouseMoveHandle = (e) => { this.setState({ x: e.clientX, y: e.clientY }) }
    

    }

    // 使用 Mouse
    <Mouse render={(point) => { return <img src={imgCat} style={{ position: 'fixed', left: point.x + 1, top: point.y + 1}}> }}></Mouse>

说明:

  • Mouse组件负责:封装复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
  • 传入的render prop负责:使用复用的状态来渲染UI结构
children代替render属性

注意:并不是该模式叫 render props 就必须使用名为render的prop,实际上可以使用任意名称的prop。把prop是一个函数并且告诉组件要渲染什么内容的技术叫做 render props模式,推荐使用 children 代替 render 属性。

class Mouse extends React.Component {
  state = { x: 0, y: 0 }
  render() { return this.props.children(this.state) }
  // 监听鼠标
  componentDidMount() {
    window.addEventListener('mousemove', this.mouseMoveHandle)
  }

  // 鼠标移动处理
  mouseMoveHandle = (e) => { this.setState({ x: e.clientX, y: e.clientY }) }
}

代码优化:

  • 给 render props 模式添加 props校验

  • 应该在组件卸载时解除 mousemove 事件绑定

    // 导入图片
    import imgCat from './cat.png'

    class Mouse extends React.Component {
    state = { x: 0, y: 0 }
    render() { return this.props.children(this.state) }
    // 监听鼠标
    componentDidMount() {
    window.addEventListener('mousemove', this.mouseMoveHandle)
    }
    // 清理工作,移除事件绑定
    componentWillUnmount() {
    window.removeEventListener('mousemove', this.mouseMoveHandle)
    }

    // 鼠标移动处理
    mouseMoveHandle = (e) => { this.setState({ x: e.clientX, y: e.clientY }) }
    

    }
    // 为 children 添加 校验
    Mouse.propTypes = {
    children: PropTypes.func.isRequired
    }

    // 使用示例
    class RenderProps extends React.Component {
    state = { show: false }
    render() {
    return (
    <>
    {
    // 条件渲染
    this.state.show && (
    <>
    <Mouse>{(point) => { return

    鼠标位置:{point.x}, {point.y}

    }}</Mouse>
    <Mouse>{(point) => { return <img src={imgCat} style={{ position: 'fixed', left: point.x + 1, top: point.y + 1}}> }}</Mouse>



    </>
    )
    }
    <button onClick={() => this.setState({ show: !this.state.show })}>{this.state.show ? '隐藏' : '显示'}</button>
    </>
    )
    }
    }
    ReactDOM.createRoot(document.getElementById('renderProps')).render(<RenderProps></RenderProps>)

高阶组件

高阶组件就相当于手机壳,通过包装组件,增强组件功能。

高阶组件(HOC,Higher-Order Component)是一个函数,接收要包装的组件,返回增强后的组件。

高阶组件内部创建一个类组件,在这个类组件中提供复用的状态逻辑代码,通过prop将复用的状态传递给被包装组件 WrappedComponent。使用步骤:

  1. 创建一个函数,名称约定以 with 开头

  2. 指定函数参数,参数应该以大写字母开头(作为要渲染的组件)

  3. 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回

  4. 在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件

  5. 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中

    // 高阶组件
    function withMouse(WrapedComponent) {
    class MouseHOC extends React.Component {
    state = { x: 0, y: 0 }
    componentDidMount() {
    window.addEventListener('mousemove', this.mouseMoveHandle)
    }
    componentWillUnmount() {
    window.removeEventListener('mousemove', this.mouseMoveHandle)
    }
    render() {
    return <WrapedComponent {...this.state}></WrapedComponent>
    }
    mouseMoveHandle = (e) => {
    this.setState({ x: e.clientX, y: e.clientY })
    }
    }

    return MouseHOC
    }
    function Position(props) {
    return (
    <>

    鼠标位置:{props.x}, {props.y}


    </>
    )
    }
    const HeightOrderCom = withMouse(Position)
    ReactDOM.createRoot(document.getElementById('heigherOrderCom')).render(<HeightOrderCom></HeightOrderCom>)

设置displayName

使用高阶组件存在的一个问题是得到组件的名称相同?

默认情况下,React使用组件名称作为displayName,解决方式是为高阶组件设置displayName,便于调试时区分不同的组件。displayName的作用是用于设置调试信息(React Developer Tools信息),设置方式:

  // 设置 displayName
  MouseHOC.displayName = `WithMouse${getDisplayName(WrapedComponent)}`

function getDisplayName(WrapedComponent) {
  return WrapedComponent.displayName || WrapedComponent.name || 'Component'
}
传递props

props丢失,原因是高阶组件没有往下传递props。解决方式是在渲染 WrappedComponent 时,将 state 和 this.props 一起传递给组件。

    render() {
      return <WrapedComponent {...this.state} {...this.props}></WrapedComponent>
    }

整体使用效果:

// 高阶组件
function withMouse(WrapedComponent) {
  class MouseHOC extends React.Component {
    state = { x: 0, y: 0 }
    componentDidMount() {
      window.addEventListener('mousemove', this.mouseMoveHandle)
    }
    componentWillUnmount() {
      window.removeEventListener('mousemove', this.mouseMoveHandle)
    }
    render() {
      return <WrapedComponent {...this.state} {...this.props}></WrapedComponent>
    }
    mouseMoveHandle = (e) => {
      this.setState({ x: e.clientX, y: e.clientY })
    }
  }
  // 设置 displayName
  MouseHOC.displayName = `WithMouse${getDisplayName(WrapedComponent)}`

  return MouseHOC
}
function getDisplayName(WrapedComponent) {
  return WrapedComponent.displayName || WrapedComponent.name || 'Component'
}
function Position(props) {
  return (
    <>
      <p>鼠标位置:{props.x}, {props.y}</p>
    </>
  )
}
function Cat(props) {
  return (
    <>
      <img src={props.img} style={{ position: 'fixed', left: props.x + 1, top: props.y + 1 }}></img>
    </>
  )
}
const MousePosition = withMouse(Position)
const MouseCat = withMouse(Cat)
class HeightOrderCom extends React.Component {
  state = { show: false }
  render() {
    return (
      <>
        {this.state.show && (
          <>
            <MousePosition></MousePosition>
            <MouseCat img={imgCat}></MouseCat>
            <br></br>
          </>
        )}
        <button onClick={() => { this.setState({ show: !this.state.show }) }}>{this.state.show ? '隐藏' : '显示'}</button>
      </>
    )
  }
}
ReactDOM.createRoot(document.getElementById('heigherOrderCom')).render(<HeightOrderCom></HeightOrderCom>)
上一篇:数据结构 —— B树
下一篇:推荐一款基于Spring Boot 框架开发的分布式文件管理系统,功能齐全,非常便捷(带私活源码)
相关推荐
B.-1 天前
Remix 学习 - @remix-run/react 中主要的 hooks
前端·javascript·学习·react.js·web
盼盼盼1 天前
如何避免在使用 Context API 时出现状态管理的常见问题?
前端·javascript·react.js
小白小白从不日白1 天前
react 动画_样式处理
前端·react.js
等下吃什么?2 天前
NEXT.js 中间件 NextResponse.redirect 无效
react.js
小白小白从不日白2 天前
react hooks--useState
前端·javascript·react.js
盼盼盼2 天前
React 项目中,如何实现有效的内存管理和防止内存泄漏?
前端·react.js·前端框架
坚持学习前端日记2 天前
react使用技巧
前端·react.js·前端框架
B.-2 天前
Remix 学习 - @remix-run/react 中的主要组件
前端·javascript·学习·react.js·web
gxhlh2 天前
React Native防止重复点击
javascript·react native·react.js
miao_zz2 天前
基于react native的锚点
android·react native·react.js
热门推荐
01RAG 实践- Ollama+RagFlow 部署本地知识库02组基轨迹建模 GBTM的介绍与实现(Stata 或 R)032024年高教社杯数学建模国赛C题超详细解题思路分析04苍穹外卖面试总结05Coze扣子平台完整体验和实践(附国内和国际版对比)06【2024数模国赛赛题思路公开】国赛B题思路丨附可运行代码丨无偿自提07CANoe Trace窗口过滤栏消失的几种解决方法(附上最终解决方案)08yolov8实战第五天——yolov8+ffmpg实时视频流检测并进行实时推流——(推流,保姆教学)09【2024高教社杯全国大学生数学建模竞赛】B题 生产过程中的决策问题——解题思路 代码 论文10【立创EDA-PCB设计基础】6.布线铺铜实战及细节详解