www
www

Reputation: 35

React. How to make function with state?

I'm learning React Native and can't understand how to make function or component instead of repeated part of my code:

export const PostScreen = () => {

    const postId = 1

    /* THIS PART IS REPEATED IN MANY FILES */
    const [data, setData] = useState([]);
    const [loader, setLoader] = useState(false);
    const [error, setError] = useState(null);
    
    const fetchData = async () => {
        setError(null)
        setLoader(true)
        try {
            const data = await Api.get(`http://localhost/api/posts/${postId}`)
            if (data.success == 1) {
                setData(data.data)
            }
            else {
                setError(data.error)
            }
            
        }
        catch(e) {
            console.log(e)
            setError('Some problems')
        }
        finally {
            setLoader(false)
        }
       
    }

    useEffect(() => {
        fetchData()
    }, [])

    if (loader) {
        return <Loader />
    }

    if (error) {
        return <View><Text>{error}</Text></View>
    }

    /*END>>> THIS PART IS REPEATED IN MANY FILES */

    return (
        <View><Text>{data.title}</Text></View>
    )
}

The problem is that fetchData is working with state. I found, how to do it with Context, but I don't wont to use it. Is there any way to do clear code without Context?

Upvotes: 0

Views: 63

Answers (1)

Mario Vernari
Mario Vernari

Reputation: 7304

So, why not make your own hook, then?

Write the hook in a dedicated module:

function useMyOwnHook(props) {
    const {
        postId,
    } = props;

    const [data, setData] = useState([]);
    const [loader, setLoader] = useState(false);
    const [error, setError] = useState(null);
    
    const fetchData = async () => {
        setError(null)
        setLoader(true)
        try {
            const data = await Api.get(`http://localhost/api/posts/${postId}`)
            if (data.success == 1) {
                setData(data.data)
            }
            else {
                setError(data.error)
            }
            
        }
        catch(e) {
            console.log(e)
            setError('Some problems')
        }
        finally {
            setLoader(false)
        }
       
    }

    useEffect(() => {
        fetchData()
    }, [])

    const render = loader
        ? <Loader />
        : error
            ? <View><Text>{error}</Text></View>
            : null;

    return {
        data,
        render,
    }
}

At that point, the component will be written as follows:

export const PostScreen = () => {

    const postId = 1

    const {
        render,
        data,
    } = useMyOwnHook({ postId });

    return render ?? (
        <View><Text>{data.title}</Text></View>
    )
}

Upvotes: 1

Related Questions