「React进阶」 React全部api解读+基础实践大全(夯实基础2万字总结)(工具类)

简介: 一份不错的 React 学习指南

接下来我们一起来探究一下react工具类函数的用法。

utils.jpg

createElement

一提到createElement,就不由得和JSX联系一起。我们写的jsx,最终会被 babel,用createElement编译成react元素形式。我写一个组件,我们看一下会被编译成什么样子,

如果我们在render里面这么写:

render(){
   
   
    return <div className="box" >
        <div className="item"  >生命周期</div>
        <Text  mes="hello,world"  />
        <React.Fragment> Flagment </React.Fragment>
        {
   
    /*  */ }
        text文本
    </div>
}
AI 代码解读

会被编译成这样:

render() {
   
   
    return React.createElement("div", {
   
    className: "box" },
            React.createElement("div", {
   
    className: "item" }, "\u751F\u547D\u5468\u671F"),
            React.createElement(Text, {
   
    mes: "hello,world" }),
            React.createElement(React.Fragment, null, " Flagment "),
            "text\u6587\u672C");
    }
AI 代码解读

当然我们可以不用jsx模式,而是直接通过createElement进行开发。

createElement模型:

React.createElement(
  type,
  [props],
  [...children]
)
AI 代码解读

createElement参数:

第一个参数:如果是组件类型,会传入组件,如果是dom元素类型,传入div或者span之类的字符串。

第二个参数::第二个参数为一个对象,在dom类型中为属性,在组件类型中为props

其他参数:,依次为children,根据顺序排列。

createElement做了些什么?

经过createElement处理,最终会形成 $$typeof = Symbol(react.element)对象。对象上保存了该react.element的信息。

cloneElement

可能有的同学还傻傻的分不清楚cloneElementcreateElement区别和作用。

createElement把我们写的jsx,变成element对象; 而cloneElement的作用是以 element 元素为样板克隆并返回新的 React 元素。返回元素的 props 是将新的 props 与原始元素的 props 浅层合并后的结果。

那么cloneElement感觉在我们实际业务组件中,可能没什么用,但是在一些开源项目,或者是公共插槽组件中用处还是蛮大的,比如说,我们可以在组件中,劫持children element,然后通过cloneElement克隆element,混入props。经典的案例就是 react-router中的Swtich组件,通过这种方式,来匹配唯一的 Route并加以渲染。

我们设置一个场景,在组件中,去劫持children,然后给children赋能一些额外的props:

function FatherComponent({
   
    children }){
   
   
    const newChildren = React.cloneElement(children, {
   
    age: 18})
    return <div> {
   
    newChildren } </div>
}

function SonComponent(props){
   
   
    console.log(props)
    return <div>hello,world</div>
}

class Index extends React.Component{
   
       
    render(){
   
         
        return <div className="box" >
            <FatherComponent>
                <SonComponent name="alien"  />
            </FatherComponent>
        </div>   
    }
}
AI 代码解读

打印:

cloneElment.jpg

完美达到了效果!

createContext

createContext用于创建一个Context对象,createContext对象中,包括用于传递 Context 对象值 valueProvider,和接受value变化订阅的Consumer

const MyContext = React.createContext(defaultValue)
AI 代码解读

createContext接受一个参数defaultValue,如果Consumer上一级一直没有Provider,则会应用defaultValue作为value只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效。

我们来模拟一个 Context.ProviderContext.Consumer的例子:

function ComponentB(){
   
   
    /* 用 Consumer 订阅, 来自 Provider 中 value 的改变  */
    return <MyContext.Consumer>
        {
   
    (value) => <ComponentA  {
   
   ...value} /> }
    </MyContext.Consumer>
}

function ComponentA(props){
   
   
    const {
   
    name , mes } = props
    return <div> 
            <div> 姓名: {
   
    name }  </div>
            <div> 想对大家说: {
   
    mes }  </div>
         </div>
}

function index(){
   
   
    const [ value , ] = React.useState({
   
   
        name:'alien',
        mes:'let us learn React '
    })
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <MyContext.Provider value={
   
   value}  >
          <ComponentB />
    </MyContext.Provider>
    </div>
}
AI 代码解读

打印结果:

createContent.jpg

ProviderConsumer的良好的特性,可以做数据的Consumer一方面传递value,另一方面可以订阅value的改变。

Provider还有一个特性可以层层传递value,这种特性在react-redux中表现的淋漓尽致。

createFactory

React.createFactory(type)
AI 代码解读

返回用于生成指定类型 React 元素的函数。类型参数既可以是标签名字符串(像是 'div' 或 'span'),也可以是 React 组件 类型 ( class 组件或函数组件),或是 React fragment 类型。

使用:

 const Text = React.createFactory(()=><div>hello,world</div>) 
function Index(){
   
     
    return <div style={
   
   {
   
    marginTop:'50px'  }} >
        <Text/>
    </div>
}
AI 代码解读

效果

createFactory.jpg

报出警告,这个api将要被废弃,我们这里就不多讲了,如果想要达到同样的效果,请用React.createElement

createRef

createRef可以创建一个 ref 元素,附加在react元素上。

用法:

class Index extends React.Component{
   
   
    constructor(props){
   
   
        super(props)
        this.node = React.createRef()
    }
    componentDidMount(){
   
   
        console.log(this.node)
    }
    render(){
   
   
        return <div ref={
   
   this.node} > my name is alien </div>
    }
}
AI 代码解读

个人觉得createRef这个方法,很鸡肋,我们完全可以class类组件中这么写,来捕获ref

class Index extends React.Component{
   
   
    node = null
    componentDidMount(){
   
   
        console.log(this.node)
    }
    render(){
   
   
        return <div ref={
   
   (node)=> this.node } > my name is alien </div>
    }
}
AI 代码解读

或者在function组件中这么写:

function Index(){
   
   
    const node = React.useRef(null)
    useEffect(()=>{
   
   
        console.log(node.current)
    },[])
    return <div ref={
   
   node} >  my name is alien </div>
}
AI 代码解读

isValidElement

这个方法可以用来检测是否为react element元素,接受待验证对象,返回true或者false。这个api可能对于业务组件的开发,作用不大,因为对于组件内部状态,都是已知的,我们根本就不需要去验证,是否是react element 元素。
但是,对于一起公共组件或是开源库,isValidElement就很有作用了。

实践

我们做一个场景,验证容器组件的所有子组件,过滤到非react element类型。

没有用isValidElement验证之前:

const Text = () => <div>hello,world</div> 
class WarpComponent extends React.Component{
   
   
    constructor(props){
   
   
        super(props)
    }
    render(){
   
   
        return this.props.children
    }
}
function Index(){
   
   
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <WarpComponent>
            <Text/>
            <div> my name is alien </div>
            Let's learn react together!
        </WarpComponent>
    </div>
}
AI 代码解读

过滤之前的效果

isValidElement.jpg

我们用isValidElement进行react element验证:

class WarpComponent extends React.Component{
   
   
    constructor(props){
   
   
        super(props)
        this.newChidren = this.props.children.filter(item => React.isValidElement(item) )
    }
    render(){
   
   
        return this.newChidren
    }
}
AI 代码解读

过滤之后效果

isValidElement111.jpg

过滤掉了非react elementLet's learn react together!

Children.map

接下来的五个api都是和react.Chidren相关的,我们来分别介绍一下,我们先来看看官网的描述,React.Children 提供了用于处理 this.props.children 不透明数据结构的实用方法。

有的同学会问遍历 children用数组方法,mapforEach 不就可以了吗? 请我们注意一下不透明数据结构,什么叫做不透明结构?

我们先看一下透明的结构:

class Text extends React.Component{
   
   
    render(){
   
   
        return <div>hello,world</div>
    }
}
function WarpComponent(props){
   
   
    console.log(props.children)
    return props.children
}
function Index(){
   
   
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <WarpComponent>
            <Text/>
            <Text/>
            <Text/>
            <span>hello,world</span>
        </WarpComponent>
    </div>
}
AI 代码解读

打印

chidrenmap.jpg

但是我们把Index结构改变一下:

function Index(){
   
   
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <WarpComponent>
            {
   
    new Array(3).fill(0).map(()=><Text/>) }
            <span>hello,world</span>
        </WarpComponent>
    </div>
}
AI 代码解读

打印

chidrenmap2.jpg

这个数据结构,我们不能正常的遍历了,即使遍历也不能遍历,每一个子元素。此时就需要 react.Chidren 来帮忙了。

但是我们把WarpComponent组件用react.Chidren处理children:

function WarpComponent(props){
   
   
    const newChildren = React.Children.map(props.children,(item)=>item)
    console.log(newChildren)
    return newChildren
}
AI 代码解读

此时就能正常遍历了,达到了预期效果。

C71364B2-25E8-4F7D-A26D-50CA36AF4E33.jpg

注意
如果 children 是一个 Fragment 对象,它将被视为单一子节点的情况处理,而不会被遍历。

Children.forEach

Children.forEachChildren.map 用法类似,Children.map可以返回新的数组,Children.forEach仅停留在遍历阶段。

我们将上面的WarpComponent方法,用Children.forEach改一下。

function WarpComponent(props){
   
   
    React.Children.forEach(props.children,(item)=>console.log(item))
    return props.children
}
AI 代码解读

Children.count

children 中的组件总数量,等同于通过 mapforEach 调用回调函数的次数。对于更复杂的结果,Children.count可以返回同一级别子组件的数量。

我们还是把上述例子进行改造:

function WarpComponent(props){
   
   
    const childrenCount =  React.Children.count(props.children)
    console.log(childrenCount,'childrenCount')
    return props.children
}   
function Index(){
   
   
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <WarpComponent>
            {
   
    new Array(3).fill(0).map((item,index) => new Array(2).fill(1).map((item,index1)=><Text key={
   
   index+index1} />)) }
            <span>hello,world</span>
        </WarpComponent>
    </div>
}
AI 代码解读

效果:

chidrencunt.jpg

Children.toArray

Children.toArray返回,props.children扁平化后结果。

function WarpComponent(props){
   
   
    const newChidrenArray =  React.Children.toArray(props.children)
    console.log(newChidrenArray,'newChidrenArray')
    return newChidrenArray
}   
function Index(){
   
   
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <WarpComponent>
            {
   
    new Array(3).fill(0).map((item,index)=>new Array(2).fill(1).map((item,index1)=><Text key={
   
   index+index1} />)) }
            <span>hello,world</span>
        </WarpComponent>
    </div>
}
AI 代码解读

效果:

chuldeanarrgy.jpg

newChidrenArray ,就是扁平化的数组结构。React.Children.toArray() 在拉平展开子节点列表时,更改 key 值以保留嵌套数组的语义。也就是说, toArray 会为返回数组中的每个 key 添加前缀,以使得每个元素 key 的范围都限定在此函数入参数组的对象内。

Children.only

验证 children 是否只有一个子节点(一个 React 元素),如果有则返回它,否则此方法会抛出错误。

不唯一

function WarpComponent(props){
   
   
    console.log(React.Children.only(props.children))
    return props.children
}   
function Index(){
   
   
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <WarpComponent>
            {
   
    new Array(3).fill(0).map((item,index)=><Text key={
   
   index} />) }
            <span>hello,world</span>
        </WarpComponent>
    </div>
}
AI 代码解读

效果

falseonly.jpg

唯一

function WarpComponent(props){
   
   
    console.log(React.Children.only(props.children))
    return props.children
}   
function Index(){
   
   
    return <div style={
   
   {
   
    marginTop:'50px' }} >
        <WarpComponent>
           <Text/>
        </WarpComponent>
    </div>
}
AI 代码解读

效果

only.jpg

React.Children.only() 不接受 React.Children.map() 的返回值,因为它是一个数组而并不是 React 元素。

目录
打赏
0
0
0
0
170
分享
相关文章
React 18 流式渲染:解锁极致性能优化实践
React 18 流式渲染:解锁极致性能优化实践
163 80
京东拍立淘图片搜索 API 接入实践:从图像识别到商品匹配的技术实现
京东拍立淘图片搜索 API 是基于先进图像识别技术的购物搜索接口,支持通过上传图片、URL 或拍摄实物搜索相似商品。它利用机器学习和大数据分析,精准匹配商品特征,提供高效、便捷的搜索体验。接口覆盖京东海量商品资源,不仅支持外观、颜色等多维度比对,还结合用户行为数据实现智能推荐。请求参数包括图片 URL 或 Base64 编码,返回 JSON 格式的商品信息,如 ID、价格、链接等,助力消费者快速找到心仪商品,满足个性化需求。
191 18
京东拍立淘图片搜索 API 接口使用指南:从原理到实践
京东拍立淘图片搜索API,基于先进图像识别技术,支持上传图片、URL或拍摄实物搜索相似商品。其特点包括:搜索便捷高效,用户可快速发起搜索;精准匹配结果,通过算法捕捉商品特征确保准确;数据覆盖广泛,依托京东海量商品资源满足个性化需求;智能推荐拓展,根据用户行为挖掘潜在需求,提升购物体验。
掌握Multi-Agent实践(三):ReAct Agent集成Bing和Google搜索功能,采用推理与执行交替策略,增强处理复杂任务能力
掌握Multi-Agent实践(三):ReAct Agent集成Bing和Google搜索功能,采用推理与执行交替策略,增强处理复杂任务能力
160 23
利用 RunnerGo 深度探索 API 性能测试:从理论到实践
API性能测试是保障应用稳定性和用户体验的关键环节。本文详细探讨了如何使用RunnerGo全栈测试平台进行高效API性能测试,涵盖测试计划创建、场景设计、参数配置到执行与分析全过程。通过电商平台促销活动案例,展示了高并发下的测试策略与优化措施,如代码与数据库查询优化、数据库连接池扩容、服务器资源配置调整及缓存策略实施等。最终显著提升系统性能,满足高并发需求。API性能测试需持续关注与优化,以适应业务发展和用户需求变化。
139 33
基于 API 网关践行 API First 开发实践
API First 开发模式的核心在于:以 API 为先,将其视为“头等公民”,在构建应用、服务及集成之前,应优先定义并设计 API 及其配套。API First 作为一种相对较新的开发模式,它已逐渐流行并获得业内的广泛认可。
323 117
使用 Node.js、Express 和 React 构建强大的 API
本文详细介绍如何使用 Node.js、Express 和 React 构建强大且动态的 API。从开发环境搭建到集成 React 前端,再到利用 APIPost 高效测试 API,适合各水平开发者。内容涵盖 Node.js 运行时、Express 框架与 React 库的基础知识及协同工作方式,还涉及数据库连接和前后端数据交互。通过实际代码示例,助你快速上手并优化应用性能。
构建智能天气助手:基于大模型API与工具函数的调用实践
在人工智能快速发展的今天,大语言模型(LLM)已经成为构建智能应用的重要基础设施。本文将介绍如何利用大模型API和工具函数集成,构建一个能够理解自然语言并提供精准天气信息的智能助手。
408 11
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
183 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
利用Postman和Apipost进行API测试的实践与优化-动态参数
在API测试中,Postman和Apipost是常用的工具。Postman内置变量功能有限,面对复杂场景时需编写JavaScript脚本,增加了维护成本。而Apipost提供丰富的内置变量、可视化动态值配置和低代码操作,支持生成真实随机数据,如邮箱、手机号等,显著提升测试效率和灵活性。对于复杂测试场景,Apipost是更好的选择,能有效降低开发与维护成本,提高测试工作的便捷性和可维护性。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问