繁体   English   中英

使用 Hooks 将 Class 组件转换为功能组件

[英]Converting Class Component to Functional Component With Hooks

我尝试在下面转换 class 组件代码:

import React, { Component } from 'react'
import ReactTable from 'react-table'
import api from '../api'

import styled from 'styled-components'

import 'react-table/react-table.css'

const Wrapper = styled.div`
    padding: 0 40px 40px 40px;
`

const Update = styled.div`  
    color: #ef9b0f;
    cursor: pointer;
`

const Delete = styled.div`
    color: #ff0000;
    cursor: pointer;
`

class UpdateVoter extends Component {
    updateUser = event => {
        event.preventDefault()

        window.location.href = `/voters/update/${this.props.id}`
    }

    render() {
        return <Update onClick={this.updateUser}>Update</Update>
    }
}

class DeleteVoter extends Component {
    deleteUser = event => {
        event.preventDefault()

        if (
            window.confirm(
                `Do you want to delete this voter ${this.props.id} permanently?`,
            )
        ) {
            api.deleteVoterById(this.props.id)
            window.location.reload()
        }
    }

    render() {
        return <Delete onClick={this.deleteUser}>Delete</Delete>
    }
}

class VotersList extends Component {
    constructor(props) {
        super(props)
        this.state = {
            voters: [],
            columns: [],
            isLoading: false,
        }
    }

    componentDidMount = async () => {
        this.setState({ isLoading: true })

        await api.getAllVoters().then(voters => {
            this.setState({
                voters: voters.data.data,
                isLoading: false,
            })
        })
    }

    render() {
        //const { voters, isLoading } = this.state

        const columns = [
            {
                Header: 'ID',
                accessor: '_id',
                filterable: true,
            },
            {
                Header: 'No KK',
                accessor: 'nkk',
                filterable: true,
            },
            {
                Header: 'NIK',
                accessor: 'nik',
                filterable: true,
            },
            {
                Header: 'Nama',
                accessor: 'nama',
                filterable: true,
            },
            {
                Header: 'Alamat',
                accessor: 'alamat',
                filterable: true,
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        <span>
                            <DeleteVoter id={props.original._id} />
                        </span>
                    )
                },
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        <span>
                            <UpdateVoter id={props.original._id} />
                        </span>
                    )
                },
            },
        ]

        let showTable = true
        if (!this.state.voters.length) {
            showTable = false
        }

        return (
            <Wrapper>
                {showTable && (
                    <ReactTable
                        data={this.state.voters}
                        columns={columns}
                        loading={this.state.isLoading}
                        defaultPageSize={10}
                        showPageSizeOptions={true}
                        minRows={0}
                    />
                )}
            </Wrapper>
        )
    }
}

export default VotersList

到这个功能组件代码:

import React, {useState, useEffect} from 'react'
import ReactTable from 'react-table'
import api from '../api'

import styled from 'styled-components'

import 'react-table/react-table.css'

const Wrapper = styled.div`
    padding: 0 40px 40px 40px;
`

const Update = styled.div`
    color: #ef9b0f;
    cursor: pointer;
`

const Delete = styled.div`
    color: #ff0000;
    cursor: pointer;
`

function UpdateVoter(props) {
    const updateUser = event => {
        event.preventDefault()

        window.location.href = `/voters/update/${props.id}`
    }

    
        return <Update onClick={updateUser}>Update</Update>

}

function DeleteVoter(props) {
    const deleteUser = event => {
        event.preventDefault()

        if (
            window.confirm(
                `Do tou want to delete this voter ${props.id} permanently?`,
            )
        ) {
            api.deleteVoterById(props.id)
            window.location.reload()
        }
    }

        return <Delete onClick={deleteUser}>Delete</Delete>
  
}

function VotersList(props) {
    const [voters, setVoters] = useState ({voters: []})
    const [isLoading, setIsLoading] = useState ({isLoading: false})

    useEffect(() => {
        async function fetchData() {
            setIsLoading(true)
            return (setVoters(await api.getAllVoters()))
        }
        console.log(fetchData())
    }, [])

        const columns = [
            {
                Header: 'ID',
                accessor: '_id',
            },
            {
                Header: 'No KK',
                accessor: 'nkk',
            },
            {
                Header: 'NIK',
                accessor: 'nik',
            },
            {
                Header: 'Nama',
                accessor: 'nama',
            },
            {
                Header: 'Alamat',
                accessor: 'alamat',
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        <span>
                            <DeleteVoter id={props.original._id} />
                        </span>
                    )
                },
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        <span>
                            <UpdateVoter id={props.original._id} />
                        </span>
                    )
                },
            },
        ]

        let showTable = true
        if (!voters.length) {
            showTable = false
        }

        return (
            <Wrapper>
                {showTable && (
                    <ReactTable
                        data={voters}
                        columns={columns}
                        loading={isLoading}
                        defaultPageSize={10}
                        showPageSizeOptions={true}
                        minRows={0}
                    />
                )}
            </Wrapper>
        )
    
}

export default VotersList

但是,我得到了空白结果。 该表不显示。 我尝试在useEffect function 中使用console.log(fetchData()) ,并在控制台中打印了这个结果Promise {<pending>} 这是什么意思? 为什么表格没有按应有的方式显示? 非常感谢您提前。

您从fetchVoter内部的useEffect setVoter这就是控制台打印 promise 的原因。

你应该这样尝试

async function fetchData() {
  const data = await api.getAllVoters()
  return data
}

async handleDataFetch() {
   setIsLoading(true)
   const data = await fetchData()
   setVoters(data)
   setIsLoading(false)
}

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

这是什么意思?

Promise {<pending>}告诉您 function 的结果是尚未解决的 promise。 async function 将在没有await的情况下调用 Promise

如果您想查看网络请求的内容,您应该在fetchData function 中使用console.log

为什么表格没有按应有的方式显示?

我认为这是因为您没有正确设置getAllVoters结果。

在您的原始代码中,您将 state 变量voters设置为来自 API 结果的data.data ,而在重构代码中,您只需将其设置为结果:

setVoters(await api.getAllVoters())

您可以通过将其更改为来解决此问题:

useEffect(() => {
    async function fetchData() {
        setIsLoading(true)
        const voters = await api.getAllVoters();
        setVoters(voters.data.data)
    }

    fetchData()
}, [])

还值得一提的是,您错误地使用useState

您正在像这样使用它:

const [isLoading, setIsLoading] = useState({ isLoading: false });

而它应该像这样使用:

const [isLoading, setIsLoading] = useState(false);

目前,您正在将变量isLoading设置为此 object: {isLoading: false}而您只是想将其设置为 false。

目前这不会给您带来问题,因为您会立即使用setIsLoading(true)将值更改为 true,但是,它可能会导致错误。

useState ({voters: []})也是如此。

我相信你没有有效地使用useEffect钩子。 我在您的代码中看到的问题很少,其中一个是将async与函数一起使用(这是正确的),但async-await的规则是,当您有async function 时,无论您调用它,您都必须await 此外,好的做法是将您的 api 逻辑放在useEffect之外,放在单独的 function 中。 我在您的代码中发现的另一个问题是您的isLoading state 被初始化为 object 但随后在您的fetctData function 值中您设置错误。 您可以简单地将其初始化为true并在获取数据后将其设置为false所以您上面的VotersList组件代码将如下所示

function VotersList(props) {
    const [voters, setVoters] = useState({voters: []})
    const [isLoading, setIsLoading] = useState(true)
    
    const fetchData = async () => {
      let allVoters = await api.getAllVoters();
      setVoters(allVoters);
      setIsLoading(false);
    }

    useEffect(async () => {
        let allVoters = await api.getAllVoters();
        setVoters(allVoters);
    }, [])
    // OR
    /*
    useEffect(async () => {
        await fetchData();
    }, [])
    */




        const columns = [
            {
                Header: 'ID',
                accessor: '_id',
            },
            {
                Header: 'No KK',
                accessor: 'nkk',
            },
            {
                Header: 'NIK',
                accessor: 'nik',
            },
            {
                Header: 'Nama',
                accessor: 'nama',
            },
            {
                Header: 'Alamat',
                accessor: 'alamat',
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        <span>
                            <DeleteVoter id={props.original._id} />
                        </span>
                    )
                },
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        <span>
                            <UpdateVoter id={props.original._id} />
                        </span>
                    )
                },
            },
        ]

        let showTable = true
        if (!voters.length) {
            showTable = false
        }

        return (
            <Wrapper>
                {showTable && (
                    <ReactTable
                        data={voters}
                        columns={columns}
                        loading={isLoading}
                        defaultPageSize={10}
                        showPageSizeOptions={true}
                        minRows={0}
                    />
                )}
            </Wrapper>
        )
    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM