Entry-level React Scroll component development

What is scroll component?

In short, the ability to scroll through the components of each project at a fixed height

Features: Scroll to the bottom to load more, error prompt, no more, no more data bottom prompt

Technology stack

react + react hooks + fetch

The development of

The first step is to write down the basic components

index.js

    function Index(props) {
        return (
            <div className={'box-container'} >
                <scroll>
                </scroll>
            </div>)}Copy the code

scroll.js

function Scroll(props) {
        return (
            <ul className={'scroll-container'} >
            2131
            </ul>)}Copy the code

item.js

function Item(props) {
    return (
        <div className={'item-container'} >{props. Children instanceof Array? props.children.map(item => item) : props.children }</div>
    );
}
Copy the code

The second step starts rendering the list data

index.js

const [list, setList] = useState([])

const [totalCount, setTotalCount] = useState(0)

const [listQuery, setListQuery] = useState({
    page: 1.rows: 10
})

// Rely on listQuery data. If the paging parameter page changes, re-send the request for new data
useEffect(() = > {
    fetchData(listQuery).then(res= > {
        console.log('listQuery change')
        const {bookList, totalCount} = res.data
        const result = [...list, ...bookList]  // Merge the previous data
        setList(result)
        setTotalCount(totalCount)
    })
}, [listQuery]);

// For a computed object similar to VUE, get the computed value when list and totalCount change
const hasMore = useMemo(() = > {
    return list.length < totalCount
}, [list, totalCount])

return (
    <div className={'box-container'} >
        <Scroll 
            sourceData = {list}
            renderItem = {item= > (
                <Item key = {item.key}>/* This is where the contents of the Item are placed, or individual data can be passed to the Item for rendering<Item key = {item.key} item={item}></Item>* /<span>{item.title}</span>
                </Item>
            )}
            hasMore = {hasMore}
        >
        </Scroll>
    </div>
)
Copy the code

scroll.js

const { sourceData, renderItem, hasMore } = props

return (
    <ul className={'scroll-container'} >
        {
            sourceData.map(renderItem)
        }
    </ul>
);
Copy the code

The third step is to determine whether to scroll to the bottom

const handleScroll = () = > {
    // No more scrolling does not need to calculate height to load more.
    if(! hasMore) {return
    }
    const sr = scrollRef.current // scroll for the outermost element
    
    const sh = sr.scrollHeight
    const ch = sr.clientHeight
    const st = sr.scrollTop
    // 
    if(sh - (st + 10) <= ch) {
        // Load more}}Copy the code

Step 4 Load more

index.js

    const [loading, setLoading] = useState(false)
    useEffect(() = > {
    +++    setLoading(true)
        fetchPageData(listQuery).then(res= > {
            console.log('listQuery change')
            const {bookList, totalCount} = res.data
            const result = [...list, ...bookList]
            // Scroll load latency
            setTimeout(() = > {
                setList(result)
                setTotalCount(totalCount)
    +++            setLoading(false)},2000)
        })
    }, [listQuery]);
    
    return (
        <div className={'box-container'} >
            <Scroll
                sourceData={list}
                renderItem={(item, index) = > (
                    <Item key={item.title}>
                        <span>{index}{index}</span>
                    </Item>} load={() => {// Pass the load event to the Scroll component. let num = listQuery.page + 1 let result = {... listQuery} result.page = num setListQuery(result) }} loading={loading} hasMore={hasMore} /></div>
    );
Copy the code

scroll.js

const handleScroll = () => { +++ if(loading) { +++ return +++ } if(! hasMore) { return } const sr = scrollRef.current const sh = sr.scrollHeight const ch = sr.clientHeight const st = Sr. scrollTop if(sh - (st + 10) <= ch) {+++ load()}} const showLoading = useMemo(() => hasMore && loading, [hasMore, loading]); return ( <ul className={'scroll-container'} ref={scrollRef} onScroll={handleScroll}> { sourceData.map(renderItem) } // You can customize the loading icon {showLoading && <div className={'loading'}> loading... </div> } </ul> );Copy the code

The above code finishes scrolling to the bottom to load more and no more.

Error message, no more data at the bottom of the function to add loading and add judgment, need to pay attention to the priority. You can also add a reload button when loading times out…

rendering

Thank you for watching

Use the react knowledge recently learned to do a small component, I hope you can point out any shortcomings.