background

In front of the big factory encountered this interview question, now have time to think about it, write down my implementation

Hooks version

Extract state using custom hooks

const defaultState = {
    status: 'idle'./ / state value: initial error | | in the | loaded successfully
    data: null.error: null,}const useFetch = (initialState) = > {
    const[state, setState] = useState({ ... defaultState, ... initialState, });const setData = (data) = > {
        setState({
            data,
            status: 'success'.error: null,})};const setError = (error) = > {
         setState({
            error,
            status: 'error'.data: null,})};// Run is passed as a promise (call interface method)
    const run = (promise) = > {
        if(! promise || ! promise.then) {throw new Error('Please pass in the Promise type.') } setState({ ... state,status: 'loading' })
        
        return promise.then(data= > {
            setData(data)
            return data;
        }).catch(err= > {
            setError(err)
            return err
        })
    }
    
    return {
        isIdle: state.status === 'idle'.isLoading: state.status === 'loading'.isError: state.status === 'error'.isSuccess: state.status === 'success', run, setData, setError, ... state, } }Copy the code

Class version

Using the render props component of higher-order components

class Fetcher extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            data: null.status: 'idle'
            error: null}}componentDidMount() {
        this.setState({ status: 'loading' })
        fetch(this.props.url) // The url passed in by the children component
            .then(res= > {
                this.setState({
                    data: res,
                    status: 'success'.error: null,
                })
            })
            .catch(error= > {
                this.setState({
                    error,
                    status: 'error'.data: null})})}render() {
        const renderProps = {
            isIdle: this.state.status === 'idle'.isLoading: this.state.status === 'loading'.isError: this.state.status === 'error'.isSuccess: this.state.status === 'success'. this.state, }return this.props.children(renderProps)
    }
}
Copy the code

use

const MyComponent = () = > {
    <Fetcher url={xxxxxxx}>{({ data, error, isLoading, isError, ... rest }) => { if(isError) { return<div>{error}</div>
            }
            if(isLoading) {
                return <div>loading...</div>} if(! data) { return<div>No Data</div>
            }
            
            return (
                <div>{data}</div>)}}</Fetcher>
}
Copy the code