![](/img/trans.png)
[英]Cannot read properties of undefined when in React component but works fine when in getStaticProps function
[英]Request to api works fine in component but not when using provider with react
當從組件向我的 API 發出請求並使用 react-data-table-component 時,一切正常,但是如果我嘗試從我的產品提供者發出請求,則分頁不正確並且不再按預期工作。
使用此代碼,我可以使組件中的請求、數據表和分頁完美運行:
import React, { useState, useEffect, useCallback, useMemo } from "react";
import axiosClient from "../config/axiosClient";
import DataTable from 'react-data-table-component-with-filter'
import { CSVLink } from "react-csv"
import { Link } from 'react-router-dom'
import useProducts from "../hooks/useProducts";
const removeItem = (array, item) => {
const newArray = array.slice();
newArray.splice(newArray.findIndex(a => a === item), 1);
return newArray;
};
const ProductsTest = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [totalRows, setTotalRows] = useState(0);
const [perPage, setPerPage] = useState(10);
const [currentPage, setCurrentPage] = useState(1);
const [searchBox, setSearchBox] = useState('')
const STRING_TRADUCTIONS = { "KILOGRAM" : "KILOGRAMOS", "GRAMS" : "GRAMOS", "BOX" : "CAJA", "PACKAGE" : "PAQUETE", "BOTTLE" : "BOTE", "PIECES" : "PIEZAS", "BAG" : "BOLSA", "LITER" : "LITRO" }
const fetchUsers = async (page, limit = perPage, search = searchBox) => {
setLoading(true)
const dataOnLs = localStorage.getItem('cmtjs')
const config = {
headers: {
"Content-Type": "application/json",
apiKey: dataOnLs
} ,
params: {
limit,
page,
search
}
}
const response = await axiosClient(`/products`, config)
const data = response.data.products.docs.map( doc => (
{
_id: doc._id,
idProduct: doc.idProduct,
barCode: doc.barCode,
name: doc.name,
presentation: STRING_TRADUCTIONS[doc.presentation],
salePrice: doc.salePrice,
purchasePrice: doc.purchasePrice,
stock: doc.stock,
user: doc.user.username,
category: doc.category.name,
provider: doc.provider.name
}
))
setData(data);
setTotalRows(response.data.products.totalDocs);
setLoading(false);
};
useEffect(() => {
fetchUsers(1)
}, []);
const columns = useMemo(
() => [
{
name: "ID",
selector: "idProduct",
sortable: true
},
{
name: "Código de Barras",
selector: "barCode",
sortable: true
},
{
name: "Nombre",
selector: "name",
sortable: true
},
{
name: "Presentación",
selector: "presentation",
sortable: true
},
{
name: "Precio",
selector: "salePrice",
sortable: true
},
{
name: "Stock",
selector: "stock",
sortable: true
},
{ cell: row =>
<Link to={ `/dashboard/product/${row._id}`}>
<button className='btn btn-ghost text-xs'>
Mas
</button>
</Link>}
]
);
const handlePageChange = page => {
fetchUsers(page);
setCurrentPage(page);
};
const handlePerRowsChange = async (newPerPage, page) => {
fetchUsers(page, newPerPage);
setPerPage(newPerPage);
}
const headers = [
{ label: "ID", key: "idProduct" },
{ label: "Código de Barras", key: "barCode" },
{ label: "Nombre", key: "name" },
{ label: "Presentación", key: "presentation" },
{ label: "Precio Venta", key: "salePrice" },
{ label: "Precio Compra", key: "purchasePrice" },
{ label: "Stock", key: "stock" },
{ label: "Creador", key: "user" },
{ label: "Categoría", key: "category" },
{ label: "Proveedor", key: "provider" }
]
const paginationComponentOptions = {
rowsPerPageText: 'Mostrar',
rangeSeparatorText: 'de',
selectAllRowsItem: true,
selectAllRowsItemText: 'Todos',
};
const clear = () => {
setPerPage(10)
setSearchBox('')
fetchUsers(1, 10, '')
}
return (
<div>
<input type="text" onChange={(e)=> setSearchBox(e.target.value)}/>
<button onClick={ ()=> fetchUsers()}>Buscar</button>
<CSVLink data={data} headers={headers} filename={"productos.cdtmx.csv"} className="cursor-pointer">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABmJLR0QA/wD/AP+gvaeTAAACnUlEQVRoge2YXUhUQRiGn7HVRVddc8k0QawQw6hQohKSlsp+oDulQBGCbuxGQ1itDIx+IIWINKK86S4o6ibFEG9ywQzCEJLVSCylorYf1CJaXXe6SPvZ1ePZs3tczfNcfsP3zfvOzHc4M2BgYGAQSYTWxJSrReUg6oHEYHNtuRu1TDkupKx27Tp38+9glJZKv9AmPgQSpYiq9w+GYGBBxU8jrf6RUAwsCgwDkcYwEGlM/gFLVf4JkBcEWJQSvw+/Ua4cJYixWjElxoemcB4CDKgRrwqfZGJ0lImpqYChFe53IZefIeAIhUX8DDJsleZkyffA8jBgNkXTe+ouXy93U2Ev+R3PSE7jU70T96VHZNrSdROphCoDHu8kZ1quAVC1u4x4cxwAdQfLMZuiaei4xevPb/VTqYDqI9Ta56Rj4Ak2SxLHCw6zaU0Wxbl7Gfw4QlPnbT01KjLLZ3RuTj9oxJ61lQp7CYUbdiAQVN5rwOOd1EvfvATVxAMfXtHcdZ+k2ATy127hzrN2nIM9emlTRVA7AJAwff4BhJj/QmfpDuwNT0pCsNPOSVA7ULA+j7Jth3g63EfXUC9H8vazJ3t72MRoQbUBsymaK0UOhBCcbbtBbUsTUkoai2uIi4nVU6Miqg2c3HeM7NWZtPc/xjnYQ8+Ii9Y+JxnJadQUHtVToyKqDOSkrqPSXopP+jj/8M+jQF3bdby+KSrspWxOz9JNpBKqmtj1fojk6oKA+Ev3CCsdO8MuKhiWx7/QYmY2A9/CVt2n/4Vgth6oBS4Cod0FfVKa3Z4fgMd/yPb8i+ay/pma30ZTD+RoXl5rxiqtqbxo7vxH83/ZA0sKw0CkWdYGxsOmQj1j/gHNBoQQDhABBXVkTEocCzifgYGBgQp+AlpMnf09Cu/RAAAAAElFTkSuQmCC"/>
</CSVLink>
<DataTable
columns={columns}
data={data}
progressPending={loading}
pagination
paginationServer
paginationTotalRows={totalRows}
paginationDefaultPage={currentPage}
onChangeRowsPerPage={handlePerRowsChange}
onChangePage={handlePageChange}
selectableRows
//onSelectedRowsChange={({ selectedRows }) => console.log(selectedRows)}
paginationComponentOptions={paginationComponentOptions}
noDataComponent="No hay resultados"
/>
{
searchBox && searchBox !== '' && <button onClick={ () => clear() }>Limpiar</button>
}
</div>
)
}
但是我有我的產品提供商,在那里我向我的所有產品發出獲取請求,避免從我的組件發出請求並在全球范圍內獲取數據,但是如果我使用我的提供商的“getProducts”,數據表的第一個視圖是正確的,當點擊一頁或下一頁時,尋呼機前進但顯示的數據沒有,例如:它顯示前10條記錄但我要求下10條,尋呼機正確前進但數據仍然是前10條記錄, 不,我知道如何使用我的提供程序並使尋呼機根據用戶的需要顯示以下數據。
這是我的供應商獲取產品數據的代碼
const getProducts = async(page, limit, search) => {
const dataOnLs = localStorage.getItem('cmtjs')
const config = {
headers: {
"Content-Type": "application/json",
apiKey: dataOnLs
} ,
params: {
page,
limit,
search
}
}
try {
const { data } = await axiosClient(`/products`, config)
setProducts(data)
} catch (error) {
所以在我的組件中,我從我的提供者那里調用“getProducts”,使用 useEffect 鈎子將產品數據放在“產品”中
useEffect(() => {
getProducts()
setData(products.products?.docs)
setTotalRows(products.products?.totalDocs)
setLoading(false)
}, []);
在我的分頁器中獲取以下 10 條產品記錄,我單擊並更改了指示正在顯示哪個頁面的文本,但數據保持與第一頁相同
const handlePageChange = page => {
getProducts(page); // it does not show the next 10 records as it happened in the fetch of my component
setCurrentPage(page); // OK
};
同理,我的瀏覽器用這種方式也不能用了,我現在只改了調用我的provider的函數,但是還是不行
<input type="text" onChange={(e)=> setSearchBox(e.target.value)}/>
<button onClick={ ()=> getProducts()}>Buscar</button>
我想知道您是否可以幫助我使用我的提供程序使我的數據表和瀏覽器工作。 謝謝。
在這段代碼中
useEffect(() => {
getProducts()
setData(products.products?.docs)
setTotalRows(products.products?.totalDocs)
setLoading(false)
}, []);
您正在調用getProducts()
,這是異步的。 然后你嘗試setData(products...)
,但是異步調用還沒有完成,所以products
還沒有更新。 當最終異步代碼終止時, useEffect
語句不會再次觸發,因為依賴數組聲明效果僅在組件掛載時執行。
而是將您的效果分成兩部分,以便在新products
可用時觸發第二個效果:
useEffect(() => {
getProducts()
}, []);
useEffect(() => {
setData(products.products?.docs)
setTotalRows(products.products?.totalDocs)
setLoading(false)
}, [products]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.