代码之家  ›  专栏  ›  技术社区  ›  Min Htet Oo

将反应组件传递到高阶函数的替代方法

  •  1
  • Min Htet Oo  · 技术社区  · 6 年前

    我使用ReactJS高阶函数来增强现有组件的API获取能力以及加载、错误视图。为了变得更加可重用,我希望另一个使用我的HOC的程序员能够添加像这样的自定义加载错误视图。

    var FetchTest = fetchableContainer({
        url:"https://jsonplaceholder.typicode.com/posts",
        loadingView: <div>..Custom Loading..</div>,
        noConnectionView: <div>.. Custom no connection view .. </div>,
        errorView: <div>Custom Error View</div>
    })(TestComponent);
    

    不幸的是,它显示了错误消息。

    或者一个类/函数(用于复合组件),但得到:object。

    有人能告诉我另一个干净优雅的代码解决方案吗。这是我的取回容器。

    import React, {Component} from 'react';
    import axios from 'axios';
    import loadingView from './loadingView.js';
    import errorView from './errorView.js';
    import noDataView from './noDataView.js';
    import noConnectionView from './noConnectionView.js';
    
    //redux imports
    import {connect} from 'react-redux';
    import {bindActionCreators} from 'redux';
    import { Link } from 'react-router';
    
    
    const fetchableContainer = (json) => (BaseComponent) => {
    
        let url = json.url || "";
        let loadingView = json.loadingView || loadingView;
        let errorView = json.errorView || errorView;
        let noConnectionView = json.noConnectionView || noConnectionView;
        let noDataView = json.noDataView || noDataView;
    
        class FetchableContainer extends React.Component{
    
            constructor(props){
            super(props);  
            this.state = {
            fetchData: null,
            loading: false,
            fetchError: null,
            interntConnection: navigator.onLine?true:false,
            };
    
        }
    
        componentDidMount(){
            this.setState({loading: true});
            axios.get(this.url,{
                headers: { 
                    'Access-Control-Allow-Origin' : '*',
                    'Access-Control-Allow-Methods' : 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
                }
    
            }).then((response)=>{
                this.setState({fetchData: response.data});
                this.setState({loading: false});
            }).catch((error)=>{
                console.log("Erorr happen");
                console.log(error);
                this.setState({fetchError: error});
            });
        }
    
        render(){
    
            if(!this.state.interntConnection){
                return <this.noConnectionView/>; 
            }
    
            if(this.state.loading){
                return <this.loadingView/>;
            }
    
            if(this.state.fetchError){
                return <this.errorView/>;
            }
    
            return (
            <BaseComponent {...this.props}{...this.state}/>
            );
        }
    }
    }
    
    export default fetchableContainer;
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   A Jar of Clay    6 年前

    首先,你的 FetchTest undefined fetchableContainer 不归还任何东西!从技术上讲,它返回一个不返回任何内容的函数。如果您确实想要使用该类,那么应该返回该类。

    此外,这似乎是一种创建组件的奇怪方式。目前,这相当于:

    var FetchTest = fetchableContainer({
        url:"https://jsonplaceholder.typicode.com/posts",
        loadingView: <div>..Custom Loading..</div>,
        noConnectionView: <div>.. Custom no connection view .. </div>,
        errorView: <div>Custom Error View</div>
    }, TestComponent);
    

    //...
    
    const fetchableContainer = (json, BaseComponent) =>
    
        class FetchableContainer extends React.Component {
    
          //...
        }
    }
    
    export default fetchableContainer;
    

    显示错误消息可能是因为您正在尝试使用 未定义 在一些你没有发布的代码中。

    https://redux.js.org/basics/usage-with-react#implementing-container-components )并将所需的参数作为 props

    例如,它可能看起来有点像这样:

    // Imports etc...
    
    class FetchableContainer extends React.Component {
        // ...
        render() {
            //...
            return this.props.BaseComponent(/* Props */);
        }
    }
    
    export default FetchableContainer; 
    
        2
  •  0
  •   Min Htet Oo    6 年前

    我刚刚发现了错误。这是因为我正在传递JSX组件并试图获取该JSX组件。通过传递返回JSX组件的函数并在FetchableContainer的render方法上获取该函数,可以解决此错误,如下所示。

    var FetchTest = fetchableContainer({
        url: 'https://jsonplaceholder.typicode.com/posts/',
        errorView: ()=> <div>Custom Error View</div>,
        LoadingView:()=><div>Custom loading</div> ,
        NoConnectionView: ()=> <div>Custom no Connection</div>
    })(TestComponent);
    

    FetchableContainer的最终代码如下所示。

    import React, {Component} from 'react';
    import axios from 'axios';
    import LoadingView from './LoadingView';
    import ErrorView from './ErrorView';
    import NoDataView from './NoDataView';
    import NoConnectionView from './NoConnectionView';
    
    //redux imports
    import {connect} from 'react-redux';
    import {bindActionCreators} from 'redux';
    import { Link } from 'react-router';
    
    
    const fetchableContainer = (json) => (BaseComponent) =>{
    
        let LoadingFetchView = json.LoadingView || LoadingView;
        let fetchUrl = json.url || "https://jsonplaceholder.typicode.com/posts/";
        let ErrorFetchView = json.ErrorView || ErrorView;
        let NoConnectionFetchView = json.NoConnectionView || NoConnectionView;
        let NoDataFetchView = json.NoDataView || NoDataView;
    
    class FetchableContainer extends React.Component{
    
            constructor(props){
    
                console.log("inside constructure");
                console.log(LoadingView);
    
            super(props);  
            this.state = {
            fetchData: null,
            loading: false,
            fetchError: null,
            interntConnection: navigator.onLine?true:false,
            };
    
    
    
        }
    
        componentDidMount(){
            this.setState({loading: true});
            axios.get(fetchUrl,{
                headers: { 
                    'Access-Control-Allow-Origin' : '*',
                    'Access-Control-Allow-Methods' : 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
                }
    
            }).then((response)=>{
                this.setState({fetchData: response.data});
                this.setState({loading: false});
            }).catch((error)=>{
                console.log("Erorr happen");
                console.log(error);
                this.setState({fetchError: error});
            });
        }
    
        render(){
    
            if(!this.state.interntConnection){
                return <NoConnectionFetchView/>; 
            }
    
            if(this.state.loading){
                return <LoadingFetchView/>;
            }
    
            if(this.state.fetchError){
                return <ErrorFetchView/>;
            }
    
            return (
            <BaseComponent {...this.props}{...this.state}/>
            );
        }
    }
    return FetchableContainer;
    }
    
    export default fetchableContainer;