如何根据 props 的值渲染组件?
Posted
技术标签:
【中文标题】如何根据 props 的值渲染组件?【英文标题】:how to render components based on the value of props? 【发布时间】:2019-11-07 05:48:30 【问题描述】:我有一个父组件Dashboard.js
。这里我有state
的三个值,即昨天、lastWeek、lastMonth,我将这个值传递给我的子组件。现在我想根据我的子组件来渲染我的数据。问题是我正在使用 componentDidMount()
生命周期方法,它只渲染一次子组件。如何根据传递给子组件的 props 渲染数据?父组件是一个反应钩子,名为DataFetchDetails
的子组件是一个基于类的组件。附上各自的代码
父组件:- Dashboard.js
import React from 'react';
import makeStyles from '@material-ui/styles';
import Tabs, Tab, Grid from '@material-ui/core';
import AppBar from '@material-ui/core/AppBar';
import Typography from '@material-ui/core/Typography';
import Box from '@material-ui/core/Box';
import PropTypes from 'prop-types';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select'
import
TotalUsers,
LoggedInUsers,
TimePicker,
UnregisteredUsers
from './components';
import DataFetchDetails from './components/DataFetchDetails';
const useStyles = makeStyles(theme => (
root:
paddingTop: theme.spacing(4),
padding: theme.spacing(4)
,
formControl:
margin: theme.spacing(1),
minWidth: 120,
,
selectEmpty:
marginTop: theme.spacing(2),
,
));
function TabPanel(props)
const children, value, index, ...other = props;
return (
<Typography
component="div"
role="tabpanel"
hidden=value !== index
id=`simple-tabpanel-$index`
aria-labelledby=`simple-tab-$index`
...other
>
<Box p=3>children</Box>
</Typography>
);
function a11yProps(index)
return
id: `simple-tab-$index`,
'aria-controls': `simple-tabpanel-$index`,
;
const Dashboard = () =>
const classes = useStyles();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) =>
setValue(newValue);
;
const [period, setPeriod] = React.useState("yesterday");
const handleChange1 = event =>
setPeriod(event.target.value);
;
return (
<div className=classes.root>
<Select
labelId="demo-simple-select-label"
id="demo-sample-select"
value=time
onChange=handleChange1
>
<MenuItem value="yesterday">Previous day</MenuItem>
<MenuItem value="lastWeek">Last Week</MenuItem>
<MenuItem value="lastMonth">Last Month</MenuItem>
</Select>
<div className=classes.root>
<AppBar position="static">
<Tabs value=value onChange=handleChange aria-label="simple tabs example">
<Tab label="CONSENT DETAILS" ...a11yProps(0) />
<Tab label="ACCOUNT DETAILS" ...a11yProps(1) />
<Tab label="DATA FETCH DETAILS" ...a11yProps(2) />
</Tabs>
</AppBar>
<TabPanel value=value index=0>
</TabPanel>
<TabPanel value=value index=1>
</TabPanel>
<TabPanel value=value index=2>
<DataFetchDetails period=period handlePeriodChange1=handleChange1 />
</TabPanel>
</div>
</div>
);
;
export default Dashboard;
子组件 DataFetchDetails.js :-
import React from 'react';
import
Card,
CardHeader,
Button,
Divider,
CardContent,
TextField,
CardActions,
FormControl,
InputLabel,
Select,
MenuItem
from '@material-ui/core';
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 TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import axios from 'axios';
import 'izitoast/dist/css/iziToast.min.css'; // loading css
import iziToast from 'izitoast/dist/js/iziToast.min.js'; // you have access to iziToast now
import 'izitoast/dist/css/iziToast.min.css';
const url = 'MY_ENDPOINT_URL';
export default class DataFetchDetails extends React.Component
constructor(props)
super(props);
this.state =
items : [],
isLoaded : true,
renderJsx: false,
componentDidMount()
this.setState(period: this.props.period);
const periodStatus =
period : this.props.period
;
console.log("Props period = ",this.props.period)
axios.post(url, periodStatus)
.then((response) =>
this.setState(period : this.props.period)
this.setState(items : [response.data]);
.catch((error) =>
console.log("Error");
);
render()
let isLoaded, items, renderJsx = this.state;
if(!isLoaded)
return <div>Loading</div>
else
return (
<div>
<div>
<Card className="Lock-user"
>
<form >
<CardHeader
title=""
/>
<Divider></Divider>
<CardContent id="form-input" className=""
>
</CardContent>
<Divider></Divider>
</form>
</Card>
</div>
<div>
<Card>
<Paper>
<Table>
<TableHead>
<TableRow>
<TableCell> success </TableCell>
<TableCell align="right">failure</TableCell>
<TableCell align="right">inProgress</TableCell>
</TableRow>
</TableHead>
<TableBody>
items.map(item => (
<TableRow key=item.success>
<TableCell component="th" scope="row">
item.success
</TableCell>
<TableCell align="right">item.failure</TableCell>
<TableCell align="right">item.inProgress</TableCell>
</TableRow>
))
</TableBody>
</Table>
console.log("Props period render = ",this.props.period)
</Paper>
</Card>
</div>
</div>
);
后端和 api 工作正常。我想根据句点的值重新渲染我的子组件。我该如何解决这个问题?
【问题讨论】:
您是否在父组件中获取周期值? 【参考方案1】:你比较道具,即 prevProps 和当前道具(this.props)里面的对象
ComponentDidUpdate
基于 props 重新渲染子组件的生命周期方法。
由于 ComponentWillReceiveProps 现已弃用。
https://egghead.io/lessons/react-refactor-componentwillreceiveprops-to-getderivedstatefromprops-in-react-16-3
浏览反应生命周期文档或https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/postrender_with_componentdidupdate.html。
【讨论】:
但是一旦调用render函数就会触发componentDidUpdate。所以,如果 componentDidUpdate 内部的 state 有任何变化,整个生命周期都会被再次调用。 ComyoponentDidUpdate 仅在第一次渲染后触发。因此,在 componentDidUpdate 中,您可以更改将重新渲染整个组件的状态。【参考方案2】:在子组件中使用componentWillRecieveProps
。
componentWillRecieveProps(props)
// props => new props passed
// this.props => current props
希望对你有帮助。
【讨论】:
以上是关于如何根据 props 的值渲染组件?的主要内容,如果未能解决你的问题,请参考以下文章
state 用作组件中的 props,状态更改不会重新渲染组件
如何将使用 Enzyme.js 渲染的组件传递给 props?
如何在 React Native 的初始渲染中多次调用组件的 prop 方法?