[英]Converting Class Component to Functional Component With Hooks
I tried to convert the class component code below:我尝试在下面转换 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
to this functional component code:到这个功能组件代码:
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
But, I got the blank result.但是,我得到了空白结果。 The table is not displayed.
该表不显示。 I tried to
console.log(fetchData())
inside useEffect
function, and I got this result Promise {<pending>}
printed in the console.我尝试在
useEffect
function 中使用console.log(fetchData())
,并在控制台中打印了这个结果Promise {<pending>}
。 What does it mean?这是什么意思? And why is the table not displayed as it should be?
为什么表格没有按应有的方式显示? Thank you very much in advance.
非常感谢您提前。
You are returning setVoter
from fetchVoter
function inside useEffect
, that's why console is printing a promise.您从
fetchVoter
内部的useEffect
setVoter
这就是控制台打印 promise 的原因。
You should try like this你应该这样尝试
async function fetchData() {
const data = await api.getAllVoters()
return data
}
async handleDataFetch() {
setIsLoading(true)
const data = await fetchData()
setVoters(data)
setIsLoading(false)
}
useEffect(() => {
handleDataFetch()
}, [])
What does it mean?
这是什么意思?
Promise {<pending>}
is telling you that the result of the function is a promise that has not yet resolved. Promise {<pending>}
告诉您 function 的结果是尚未解决的 promise。 An async
function will return a Promise when invoked without await
; async
function 将在没有await
的情况下调用 Promise ;
If you want to view the contents of your network request you should console.log
within your fetchData
function.如果您想查看网络请求的内容,您应该在
fetchData
function 中使用console.log
。
And why is the table not displayed as it should be?
为什么表格没有按应有的方式显示?
I think this is occurring because you are not setting the getAllVoters
result correctly.我认为这是因为您没有正确设置
getAllVoters
结果。
In your original code you set the state variable voters
to data.data
from the API result, whereas in the refactored code you simple set it to the result with:在您的原始代码中,您将 state 变量
voters
设置为来自 API 结果的data.data
,而在重构代码中,您只需将其设置为结果:
setVoters(await api.getAllVoters())
You could fix this by changing it to:您可以通过将其更改为来解决此问题:
useEffect(() => {
async function fetchData() {
setIsLoading(true)
const voters = await api.getAllVoters();
setVoters(voters.data.data)
}
fetchData()
}, [])
It is also worth mentioning that you are using useState
incorrectly.还值得一提的是,您错误地使用
useState
。
You are using it like this:您正在像这样使用它:
const [isLoading, setIsLoading] = useState({ isLoading: false });
Whereas it should be used like this:而它应该像这样使用:
const [isLoading, setIsLoading] = useState(false);
At the moment you are setting the variable isLoading
to this object: {isLoading: false}
whereas you simply want to set it to false.目前,您正在将变量
isLoading
设置为此 object: {isLoading: false}
而您只是想将其设置为 false。
This isn't causing you problems at the moment as you are immediately changing the value to true with setIsLoading(true)
, however, it will probably cause bugs down the line.目前这不会给您带来问题,因为您会立即使用
setIsLoading(true)
将值更改为 true,但是,它可能会导致错误。
The same is true for useState ({voters: []})
. useState ({voters: []})
也是如此。
I believe you're not using useEffect
hook effectively.我相信你没有有效地使用
useEffect
钩子。 There are few problems I've seen in your code one of them is using async
with a function(which is correct) but the rule of async-await
is that when you have an async
function you got to await
wherever you call it.我在您的代码中看到的问题很少,其中一个是将
async
与函数一起使用(这是正确的),但async-await
的规则是,当您有async
function 时,无论您调用它,您都必须await
。 Also the good practice is to put your api logic outside useEffect
in a separate function.此外,好的做法是将您的 api 逻辑放在
useEffect
之外,放在单独的 function 中。 There's one more issue I found in your code is your isLoading
state is initialized as an object but then in your fetctData
function you're set-ting it as a bool value which is wrong.我在您的代码中发现的另一个问题是您的
isLoading
state 被初始化为 object 但随后在您的fetctData
function 值中您设置错误。 You can simply initialized it to be true
and set it to false
after data has been fetched So your above component code of VotersList
will look something like this您可以简单地将其初始化为
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.