【发布时间】:2021-04-20 21:10:55
【问题描述】:
我希望我的程序在尝试渲染任何内容之前运行使用效果。计划是使用getTable()函数获取数据,然后将数据存储在redux中,然后将当前的js文件再分解一些,以便能够访问我所有类中的数据。
所以这是它调用 createMap 函数 4 或 5 次的问题,最重要的是,它是在程序有机会将数据添加到 redux 存储并有适当的数据供 createMap 函数运行之前执行此操作。
import react, { useEffect, useState } from 'react'
import axios from 'axios';
import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableHead from '@material-ui/core/TableHead';
import TablePagination from '@material-ui/core/TablePagination';
import TableRow from '@material-ui/core/TableRow';
import dom from 'react-dom'
import L from "leaflet";
//import MarkerCluster from "./Markers"
import '../../node_modules/leaflet/dist/leaflet.css'
import '../../node_modules/react-leaflet-markercluster/dist/styles.min.css'
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'
import MarkerClusterGroup from 'react-leaflet-markercluster';
import './CSS/Pmap.css'
import { useSelector, useDispatch } from "react-redux";
function Pmap() {
const state = useSelector((state) => state)
const dispatch = useDispatch();
console.log(state)
const [data, setData] = useState();
const [rows, setRows] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
console.log('use effect')
getTable();
}, [])
const storeData = (data) => {
console.log(`store data called ${data.rows}`)
dispatch({
type: "addData",
payload: { rows: data.rows, rowCount: data.rowCount }
})
console.log(`store data finished` + state)
}
const getTable = () => {
try {
const response = axios.post("/api/get/1919")
storeData(response.data);
setLoading(false);
setData(response.data)
setRows(response.data.rows)
} catch (err) {
console.log(err);
}
}
//********************************************* Map ************************************ */
const customMarker = new L.Icon({
iconUrl: "https://unpkg.com/leaflet@1.5.1/dist/images/marker-icon.png",
iconSize: [25, 41],
iconAnchor: [10, 41],
popupAnchor: [2, -40]
});
function createMap() {
console.log("map function called for");
return (
<div>
<MapContainer center={[43.458, -80.503]} zoom={12} scrollWheelZoom={true} className='markercluster-map'>
<TileLayer
attribution='© <a href="© <a href="https://stadiamaps.com/">Stadia Maps</a>, © <a href="https://openmaptiles.org/">OpenMapTiles</a> © <a href="http://openstreetmap.org">OpenStreetMap</a> contributorshttp://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png"
/>
<MarkerClusterGroup>
{console.log(`state.rows : ${state}`)}
{
state.rows.map((element) => {
return (
<Marker
position={[element.Lat, element.Long]}
icon={customMarker}
key={element.OID} />
)
})
}
</MarkerClusterGroup>
</MapContainer>
</div>
)
}
/**********************************************End of Map ******************************* */
// ********************************************TABLE************************************
const columns = [
{ id: 'last_name', label: 'Last Name', minWidth: 170 },
{ id: 'first_name', label: 'First Name', minWidth: 100 },
{ id: 'edited_occ', label: 'Occupation', minWidth: 170 },
{ id: 'Chgd_add', label: 'Address', minWidth: 170 }
];
const useStyles = makeStyles({
root: {
width: '100%',
},
container: {
maxHeight: 440,
},
});
function StickyHeadTable() {
console.log("Sticky Head Table Called")
const classes = useStyles();
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(+event.target.value);
setPage(0);
};
return (
<Paper className={classes.root}>
<TableContainer className={classes.container}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={row.code}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{column.format && typeof value === 'number' ? column.format(value) : value}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
);
}
// ******************************************* End of table *********************************
return (
<div className="Pmap">
<div>
{createMap()}
</div>
<div>
{StickyHeadTable()}
</div>
{console.log(`state.rows end : ${JSON.stringify(state)}`)}
</div>
)
} export default Pmap;
这是控制台日志,所有这些都在 useEffect 之前运行,我认为应该在其他任何东西有机会运行之前先运行它。我还检查了它最终是否会在需要之前将数据添加到 redux。
【问题讨论】:
-
useEffect在每次完成渲染之后运行,而不是之前。 -
axios.post("/api/get/1919")返回一个 Promise,它没有data属性,因此state.rows可能在随后的渲染周期中未定义(IDK,也可能是您的状态/减速器/选择器不正确)。你的意思是让getTableasync和await回复?或者您可能打算使用 Promise 链?
标签: reactjs asynchronous redux react-redux use-effect