react(十一)-- react 高级

本文介绍了React中的高级用法,包括如何正确使用Fragment避免DOM节点的增加、错误边界的实现来提升用户体验、高阶组件的应用场景及实现方式,以及通过axios进行网络请求获取数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

react - high

  1. fragment
    01
<script type="text/babel">
    class Table extends React.Component {
        render() {
            return (
                <table>
                    <tr>
                        <td>你好</td>
                        <td>世界</td>
                    </tr>
                </table>
            )
        }
    }
    ReactDOM.render(<Table />, document.getElementById("app"));
</script>

在这里插入图片描述
         02

<script type="text/babel">
    class Table extends React.Component {
        render() {
            return (
                <table>
                    <tr>
                        <Coloumn />
                    </tr>
                </table>
            )
        }
    }
    function Coloumn () {
        return (
            <div>
                <td>你好</td>
                <td>世界</td>
            </div>
        )
    }
    ReactDOM.render(<Table />, document.getElementById("app"));
</script>

在这里插入图片描述

出现以上问题是因为:tr 中应该放 td ,不应该是 div
那么该如何解决呢?

         03 Fragment 给子元素分组,不需要向子元素添加额外的DOM节点

<script type="text/babel">
    class Table extends React.Component {
        render() {
            return (
                <table>
                    <tr>
                        <Coloumn />
                    </tr>
                </table>
            )
        }
    }
    // 写法一
    // function Coloumn () {
    //     return (
    //         <React.Fragment>
    //             <td>你好</td>
    //             <td>世界</td>
    //         </React.Fragment>
    //     )
    // }
    // 写法二:短语法
    function Coloumn () {
        return (
            <>
                <td>你好</td>
                <td>世界</td>
            </>
        )
    }
    ReactDOM.render(<Table />, document.getElementById("app"));
</script>

在这里插入图片描述
         04 注意:短语法不支持key
         Fragment方式

<script type="text/babel">
    const posts = [
        {id:1,title:'a',contect:'a-content'},
        {id:2,title:'b',contect:'b-content'},
        {id:3,title:'c',contect:'c-content'}
    ]
    function Blogs(props) {
        const {posts} = props
        return (
            <dl>
                {
                    posts.map(item=>(
                        <React.Fragment key={item.id}>
                            <dt>{item.title}</dt>
                            <dd>{item.contect}</dd>
                        </React.Fragment>
                    ))
                }     
            </dl>
        )
    }
    ReactDOM.render(<Blogs posts={posts}/>, document.getElementById("app"));
</script>

在这里插入图片描述
         短语法方式
在这里插入图片描述
在这里插入图片描述

  1. errorboundary
    01 案例:点击到5时,抛出问题 – throw
<script type="text/babel">
    class BugCount extends React.Component {
        state = { count: 0 }
        handleClick = () => {
            this.setState(({ count }) => {
                return { count: count + 1 }
            })
        }
        render() {
            if(this.state.count === 5) {
                throw new Error('count error')
            }
            return <h1 onClick={this.handleClick}>{this.state.count}</h1>
        }
    }
    ReactDOM.render(<BugCount />, document.getElementById("app"));
</script>

在这里插入图片描述

  • 使用 throw 页面直接挂掉,用户体验不好

         02 案例:点击到5时,抛出问题 – ErrorBoudary

  • 需求:程序错误 不应该导致应用崩溃
  • 作业:错误编辑本身是一个组件,能捕获子组件的错误,但是无法捕获自身错误
  • 渲染:如果子组件出现错误,则渲染错误边界自定义的错误页面,而不是直接渲染错误或空白
  • 思路:声明错误状态 - 捕获子组件错误 - 错误同步到state
    -> 有错误:渲染自定义的错误页面
    -> 没错误:渲染子组件
<script type="text/babel">
    class BugCount extends React.Component {
        state = { count: 0 }
        handleClick = () => {
            this.setState(({ count }) => {
                return { count: count + 1 }
            })
        }
        render() {
            if (this.state.count === 5) {
                throw new Error('count error')
            }
            return <h1 onClick={this.handleClick}>{this.state.count}</h1>
        }
    }

    class ErrorBoudary extends React.Component {
        // 01 错误容器
        state = { error: null, errorInfo: null }

        // 02 钩子函数:子组件发生错误异常 会被错误边界捕获 (react自动执行componentDidCatch,并传入错误信息)
        componentDidCatch(error, errorInfo) {
            console.log('----componentDidCatch');
            // 03 同步
            this.setState({
                error,
                errorInfo
            })
            console.log(error);
            console.log(errorInfo);
        }
        render() {
            const { error, errorInfo } = this.state
            // 04 页面渲染
            // 有错误
            if (error || errorInfo) {
                return (
                    <div>
                        <h2>Something go wrong</h2>
                        <details style={{whiteSpace:'pre-wrap'}}>
                            {error && error.toString()}
                            <br />
                            {errorInfo && errorInfo.toString()}
                        </details>
                    </div>
                )
            }
            // 没错误
            return this.props.children
        }
    }

    function App() {
        return (
            <div>
                <h1>App</h1>
                <ErrorBoudary>
                    <BugCount />
                </ErrorBoudary>
            </div>
        )
    }
    ReactDOM.render(<App />, document.getElementById("app"));
</script>

在这里插入图片描述

// 错误边界包裹 多个子组件,有一个组件出现问题,错误边界自定义的错误页面 会覆盖所有子组件
function App() {
    return (
        <div>
            <h1>App</h1>
            <ErrorBoudary>
                <BugCount />
                <BugCount />
                <BugCount />
            </ErrorBoudary>
        </div>
    )
}

在这里插入图片描述

// 错误边界 各自独立包裹子组件 : 互相不影响 各自提示独立的错误信息
function App() {
    return (
        <div>
            <h1>App</h1>
            <ErrorBoudary >
                <BugCount />
            </ErrorBoudary>
            <ErrorBoudary >
                <BugCount />
           </ErrorBoudary>
           <ErrorBoudary >
                <BugCount />
            </ErrorBoudary>
        </div>
    )
}

在这里插入图片描述

  1. A higher-order component (HOC) 高阶组件 一种模式 / 高级技术
  • 作用 : 对现有的组件的增强
  • 场景 :
    代码复用 : 将多个组件的公共代码抽离出来
    使用三方组件 : 保护三方组件 =>原有组件 不受侵害

         01

<script type="text/babel">
    class A extends React.Component {
        common() {
            return 'common function logic'
        }

        render() {
            return (
                <div>
                    <h1>A component</h1>
                    {
                        this.common()
                    }
                </div>
            )
        }
    }

    class B extends React.Component {

        common() {
            return 'common function logic'
        }

        render() {
            return (
                <div>
                    <h1>B component</h1>
                    {
                        this.common()
                    }
                </div>
            )
        }
    }

    class App extends React.Component {

        render() {
            return (
                <div>
                    <h1>App component</h1>
                    <A></A>
                    <B></B>
                </div>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById("app"));
</script>

在这里插入图片描述
         02

<script type="text/babel">
    //   参数 首字母大写 : 组件;  返回值 也应该是一个组件
    let HOC = (Component) => {
        return class _ extends React.Component {
            // 增强 : 封装公共逻辑
            common = () => {
                return "commmon function logic";
            };

            render() {
                // 将增强内容 通过props 注入到每个组件里面
                return <Component common={this.common} />;
            }
        };
    };

    class A extends React.Component {
        render() {
            return (
                <div>
                    <h1>A component</h1>
                    {this.props.common()}
                </div>
            );
        }
    }

    class B extends React.Component {
        render() {
            return (
                <div>
                    <h1>B component</h1>
                    {this.props.common()}
                </div>
            );
        }
    }

    let HocA = HOC(A)
    let HocB = HOC(B)

    class App extends React.Component {
        render() {
            return (
                <div>
                    <h1>App component</h1>
                    <HocA></HocA>
                    <HocB></HocB>
                </div>
            );
        }
    }

    ReactDOM.render(<App />, document.getElementById("app"));
</script>
  1. ajax
    01 axios _ 案例:获取star最多的仓库
<script type="text/babel">

    class App extends React.Component {
        state = {
            repoName: '',
            repoUrl: '',
        }
        render() {
            const { repoName, repoUrl } = this.state
            return (
                <div>
                    <h1>most stars repo is <a href={repoUrl}>{repoName}</a></h1>
                </div>
            )
        }

        componentDidMount() {
            const {url} = this.props
            // 不推荐使用:ajax - promise ajax(用ajax封装promise)
            // fetch
            // axios

            axios.get(url)
            .then(response=>{

                let result = response.data
                console.log(result);

                // 获取star最多的仓库
                let repo = result.items[0]
                console.log(repo);

                let {name,html_url} = repo
                this.setState({
                    repoName: name,
                    repoUrl: html_url
                }})
        }
    }
    const url = 'https://api.github.com/search/repositories?q=reac&sort=stars'
    ReactDOM.render(<App url={url}/>, document.getElementById("app"));
</script>

在这里插入图片描述
         02 axios _ 案例

<script type="text/babel">
    class App extends React.Component {
        state = {
            repoName: '',
            repoUrl: '',
            repos: []
        }
        render() {
            const { repoName, repoUrl, repos } = this.state
            return (
                <div>
                    <h1>most stars repo is <a href={repoUrl}>{repoName}</a></h1>
                    <ul>
                        {
                            repos.map(repo=>{
                                return <li key={repo.id}><a href={repo.html_url}>{repo.name}</a></li>
                            })
                        }
                    </ul>
                </div>
            )
        }

        componentDidMount() {
            const { url } = this.props
            axios.get(url)
                .then(response => {

                    let result = response.data
                    console.log(result);

                    let repos = result.items                    
                    this.setState({
                        repos
                    })
                })
        }
    }
    const url = 'https://api.github.com/search/repositories?q=vue&sort=stars'
    ReactDOM.render(<App url={url} />, document.getElementById("app"));
</script>

在这里插入图片描述
         03 fetch _ 案例

<script type="text/babel">
    class App extends React.Component {
        state = {
            repoName: '',
            repoUrl: '',
            repos: []
        }
        render() {
            const { repoName, repoUrl, repos } = this.state
            return (
                <div>
                    <h1>most stars repo is <a href={repoUrl}>{repoName}</a></h1>
                    <ul>
                        {
                            repos.map(repo => {
                                return <li key={repo.id}><a href={repo.html_url}>{repo.name}</a></li>
                            })
                        }
                    </ul>
                </div>
            )
        }

        componentDidMount() {
            const { url } = this.props

            fetch(url, { method: 'GET' })
                .then(response => response.json())
                .then(
                    data => {
                        console.log(data);
                        // 获取star最多的仓库
                        let repo = data.items[0]
                        console.log(repo);

                        let { name, html_url } = repo
                        this.setState({
                            repoName: name,
                            repoUrl: html_url
                        })
                   }
              )
        }
    }
    const url = 'https://api.github.com/search/repositories?q=reac&sort=stars'
    ReactDOM.render(<App url={url} />, document.getElementById("app"));
</script>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值