如何根据 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 的值渲染组件?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据我在 ReactJS 中悬停的内容来渲染组件?

state 用作组件中的 props,状态更改不会重新渲染组件

如何将使用 Enzyme.js 渲染的组件传递给 props?

如何在 React Native 的初始渲染中多次调用组件的 prop 方法?

React:Conditional Rendering(条件渲染)

根据条件渲染 JSX 元素