[英]Converting React Class component to Function Component With Hook
我嘗試在下面的反應應用程序中轉換 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 (!voters.length) {
showTable = false
}
return (
<Wrapper>
{showTable && (
<ReactTable
data={voters}
columns={columns}
loading={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 VotersListSpecific(props) {
const [state, setState] = useState ({
voters: [],
columns: [],
isLoading: false,
})
useEffect(() => {
async function fetchData() {
setState({ ...state, isLoading: true })
let voters = await api.getAllVoters()
setState({
voters: voters.data.data,
...state,
isLoading: true,
})
}
fetchData()
console.log(fetc)
}, [])
const { voters, isLoading } = state
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
但是,代碼不起作用。 該表不顯示。 state 中的“voters”數組為空。 除此之外,我還收到了以下警告:
React Hook useEffect 缺少依賴項:'state'。 包括它或刪除依賴數組。 如果您只需要在 'setState' 調用 react-hooks/exhaustive-deps 中需要 'state',您也可以進行功能更新 'setState(s =>...)'
我真的需要幫助來解決這個問題。 先感謝您。
首先, useState
不像this.state
組件中的 this.state。 建議您為每個原語state分配一個useState
function。 例如,在您的VotersListSpecific
columns
voters
,您可以使用以下isLoading
:
const [voters, setVoters] = useState([])
const [columns, setColumns] = useState([])
const [isLoading, setLoading] = useState(false)
仍然可以使用useReducer
進一步優化它,但現在它太離題了。 有興趣可以查看官方文檔。
現在讓我們來分析一下你做對了什么,做錯了什么。
當您更改 state 時,您使用語法setState({...state, isLoading: true })
,這是正確的,因為 React 僅在 ZA8CFDE6331BD46EB2AC96F8 的引用更改時切換重新渲染。 如果你使用這樣的東西:
state.isLoading = false
setState(state)
如果 state 的引用在這種情況下沒有改變,所以 React 不會重新渲染。
當您調用const { voters, isLoading } = state
時, voters
變量指向 state 的voters
字段,該字段在第一次渲染時是一個空數組。 一段時間后,當新的state
與新的voters
一起創建時,新的state.voters
實際上指向一個新數組。 但是 React 不知道這個變化,因為你已經明確地將voter
變量指向原始的空數組,這是舊的state
的一個字段。
對此的修復將類似於:
const [voters, setVoters] = useState([])
useEffect(async () => {
setVoters(await api.getAllVoters())
}, [])
return (
<ReactTable data={voters}/>
)
另一種方法是使用data={state.voters}
。
歡迎來到 React 函數式編程。
我沒有你所有的依賴,所以我試圖通過眼睛而不是實際編譯來回答你的問題。
更新 state 時的一粒鹽,而不是這樣做:
setState({
...state,
...yourstuffhere
})
做這個:
setState(prevState => {
return {
...prevState,
...yourstuffhere
}
});
發生的情況是通過上述操作,您確保您已從以前的 state 更新數據。 請記住, setState
是一個異步 function。 除非您這樣做,否則您可能會不小心丟失一些數據。
useEffect(() => {
async function fetchData() {
setState(prevState => {
return {
...prevState, isLoading: true
}
})
let voters = await api.getAllVoters()
setState(prevState => {
return {
voters: voters.data.data,
...prevState,
isLoading: true,
}
})
}
fetchData()
console.log(fetc)
}, [])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.