React & Render Props

话不多说,直接从一个例子开始,点击元素,为当前元素随机改变一种背景色
实现这个功能很简单,只需要定义个变量来存储颜色,然后为元素添加一个点击事件,点击后更新颜色。

import React, { useState } from 'react';
const ChangeBgColor = (props) => {
    const [color, setColor] = useState('#fff');
    const randomNumber = () => {
        return Math.floor(Math.random() * 255);
    };
    const change = () => {
        setColor(`rgb(${randomNumber()},${randomNumber()},${randomNumber()})`);
        console.warn(color);
    };
    return (
        <div
            style={{
                backgroundColor: color
            }}
            onClick={change}
        >
            改变背景色
        </div>
    );
};
export default ChangeBgColor;

在这里插入图片描述

如果很多地方都需要使用这个功能,一直copy简单的操作,会显得我们很low,有必要把这个功能抽成一个组件。

先想一下这个组件的功能是什么,是更换背景色,颜色属性与改变颜色的方法都应该在这个组件中实现。但是元素内容是变化的,所以内容是父组件传递下来的,可以使用 props 来接受。于是就有了下面的代码:

import React, { useState } from 'react';

const ChangeBgColor = (props) => {
    const {
        render
    } = props;
    const [color, setColor] = useState('#fff');
    const randomNumber = () => {
        return Math.floor(Math.random() * 255);
    };

    const change = () => {
        setColor(`rgb(${randomNumber()},${randomNumber()},${randomNumber()})`);
    };

    return (
        <div
            style={{
                backgroundColor: color
            }}
            onClick={change}
        >
            {
                render()
            }
        </div>
    );
};

export default ChangeBgColor;

使用组件:

<ChangeBgColor
    render={
        () => {
            return (
                <div>
                    改变背景色
                </div>
            );
        }
    }
/>

很明显这种方式存在问题,并没有真正意义上改变目标元素的背景色,只是在原来的基础上套了一层而已。如果组件内容本身存在背景色的话,连效果都看不到了。

既然 render 接收的是一个函数,我们可以利用 render 进行传参,把颜色与改变颜色方法传入 render 中,在函数内部直接使用不就可以了么:

import React, { useState } from 'react';
const ChangeBgColor = (props) => {

    const {
        render
    } = props;

    const [color, setColor] = useState('#fff');

    const randomNumber = () => {
        return Math.floor(Math.random() * 255);
    };

    const change = () => {
        setColor(`rgb(${randomNumber()},${randomNumber()},${randomNumber()})`);
    };

    return (
        <div>
            {
                render(color, change)
            }
        </div>
    );

};

export default ChangeBgColor;

使用组件:

<ChangeBgColor
    render={
        (color, change) => {
            return (
                <div
                    style={{
                        backgroundColor: color
                    }}
                    onClick={change}
                    >
                    改变背景色
                </div>
            );
        }
    }
/>

通过render方法接受组件内部的属性与方法来控制其行为,这样就可以达到功能与内容分离的目的,使功能可以更加灵活的被复用。

props 来接受 render 方法,这就是render props名字的由来。当然这里的属性名 render 是可以改成任意其他名字的。

不过每次使用时还是需要将内容传递给一个属性,看起来也不舒服,我们可以利用react的自带的props.children属性来传递 render

import React, { useState } from 'react';
const ChangeBgColor = (props) => {

    const {
        render
    } = props;

    const [color, setColor] = useState('#fff');

    const randomNumber = () => {
        return Math.floor(Math.random() * 255);
    };

    const change = () => {
        setColor(`rgb(${randomNumber()},${randomNumber()},${randomNumber()})`);
    };

    return (
        <div>
            {
                render(color, change)
            }
        </div>
    );

};

export default ChangeBgColor;

使用组件:

<ChangeBgColor>
    {
        (color, change) => {
            return (
                <div
                    style={{
                        backgroundColor: color
                    }}
                    onClick={change}
                >
                    改变背景色
                </div>
            );
        }
    }
</ChangeBgColor>

你还可以利用这些参数做一些其他的事情,比如说想显示当前的背景色的值:

<ChangeBgColor>
    {
        (color, change) => {
            return (
                <Fragment >
                    <div>
                    	当前背景色:{color}
                    </div>
                    <div
                        style={{
                            backgroundColor: color
                        }}
                        onClick={change}
                    >
                        改变背景色
                    </div>
                </Fragment>
            );
        }
    }
</ChangeBgColor>
如果你觉得我的文章对你有帮助的话,点个赞支持下吧
欢迎访问我的个人网站(相信你会喜欢上我的风格):www.dengzhanyong.com
关注我的个人公众号【前端筱园】,不错过我的每一篇推送
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端筱园

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值