I tried to convert the class component code below:
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. 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.
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. An async
function will return a Promise when invoked without await
;
If you want to view the contents of your network request you should console.log
within your fetchData
function.
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.
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:
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.
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.
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.
The same is true for useState ({voters: []})
.
I believe you're not using useEffect
hook effectively. 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. Also the good practice is to put your api logic outside useEffect
in a separate 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. 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
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>
)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.