反应。如何使功能与状态?

React. How to make function with state?

我正在学习 React Native,无法理解如何制作函数或组件而不是重复我的部分代码:

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>
    )
}

问题是 fetchData 正在处理状态。我发现,如何使用 Context 做到这一点,但我不习惯使用它。有什么办法可以在没有上下文的情况下做清晰的代码吗?

那么,为什么不自己制作 hook 呢?

在专用模块中编写挂钩:

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,
    }
}

到时候,组件会写成这样:

export const PostScreen = () => {

    const postId = 1

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

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