首页 > 解决方案 > 如何在使用 useEffect 和 setState 时有条件地呈现某些数据?

问题描述

我有一个父组件 EventPage 和一个子组件 UpcomingEvent。在 UpcomngEvent 组件中,我有我的 useEffect (不确定它是否应该存在或在 EventPage 组件中。我想要做的是:如果有即将发生的事件,我希望呈现某个代码部分,如果即将发生的事件为 null 我想渲染一段不同的代码。这是 UpcomingEvent 的代码:

import React, { useEffect, useState } from 'react'
import UpcomingShowFlyerDesktop from 'assets/images/flyer-desktop.png'
import UpcomingShowFlyerMobile from 'assets/images/flyer-mobile.png'
import { Grid } from '@material-ui/core'
import useStyles from '../styles'

function UpcomingEvent({ title, date, location, about }) {
  const classes = useStyles()
  const [upcomingEvent, setUpcomingEvent] = useState(null)
  useEffect(() => {
    setUpcomingEvent(
      (upcomingEvent) =>
        ({
          ...upcomingEvent,
          title: title,
          date: date,
          location: location,
          about: about,
        }[title][date][location][about])
    )
  })
  return (
    <div>
      <div className={classes.upcomingShowsMobile}>
        <div className={classes.titleContainerMobile}>
          <p className={classes.upcomingShowTitleMobile}>
            {title}
          </p>
        </div>
        <div className={classes.dateLocationContainerMobile}>
          <p className={classes.upcomingShowDateLocationMobile}>
            {date} | {location}
          </p>
        </div>
        <div className={classes.aboutContainerMobile}>
          <p className={classes.aboutUpcomingShowMobile}>
            {about}
          </p>
        </div>
        <div className={classes.upcomingShowButtonContainerMobile}>
          <button className={classes.upcomingShowButtonMobile}>
            BUY TICKETS
          </button>
        </div>
      </div>

这是父组件EventPage:

const EventsPage = () => {
  const classes = useStyles()
  const [events, setEvents] = useState(EVENTS)
  // const startDate = '04/23/2021'
  // const endDate = '05/04/2021'
  return (
    <div>
      {/*-------------Mobile View--------------------- */}
      <Grid
        container
        direction='column'
        justify='center'
        alignItems='center'
        spacing={0}
        className={classes.allContainerMobile}
      >
        <div className={classes.headingContainerMobile}>
          <div>
            <p className={classes.allEventsTitleMobile}>ALL EVENTS</p>
          </div>
          {UpcomingEvent === null ? (
            <div>
              <div className={classes.parentDivImageMobile}>
                <div className={classes.ImageDivMobile}>
                  <img
                    src={EventsHeroImageMobile}
                    className={classes.placeHolderImageMobile}
                  />
                </div>
              </div>
            </div>
          ) : (
            <div>
              <Grid item sm={12} className={classes.gridMobile}>
                <div className={classes.countdownContainerMobile}>
                  <div className={classes.countdownParentMobile}>
                    <CountdownTimer
                      countdown={startDate}
                      unixEndDate={endDate}
                    />
                  </div>
                </div>
              </Grid>
            </div>
          )}
          {UpcomingEvent === null ? (
            <div>
              <div>
                <p className={classes.upcomingShowMobile}>UPCOMING SHOW</p>
              </div>
              <div>
                <p className={classes.noUpcomingShowsMobile}>
                  NO UPCOMING SHOWS...FOR NOW.
                </p>
              </div>
            </div>
          ) : (
            <div>
              <div className={classes.flyerImageMobile}>
                <div className={classes.upcomingShowParentMobile}>
                  <img
                    src={UpcomingShowFlyerMobile}
                    className={classes.imageStyleMobile}
                  />
                </div>
              </div>
            </div>
          )}
        </div>
        {UpcomingEvent !== null ? (
          <div>
            <UpcomingEvent
              title={title}
              date={date}
              location={location}
              about={about}
            />
          </div>
        ) : null}
        {UpcomingEvent === null ? (
          <div>
            <h2 className={classes.pastShowsMobile}>PAST SHOWS</h2>
          </div>
        ) : (
          <div>
            <h2 className={classes.pastShowsUpcomingMobile}>PAST SHOWS</h2>
          </div>
        )}

        <div className={classes.eventsCardMobile}>
          {events.map(({ month, day, title, time, location }, i) => (
            <BasicCard
              key={`${title}-${i}`}
              month={month}
              day={day}
              title={title}
              time={time}
              location={location}
            />
          ))}
        </div>
      </Grid>

标签: javascriptreactjsreact-hookscomponentsconditional-statements

解决方案


我把我的 useEffect 钩子放在了错误的地方,并且使用了错误的标准。经过一番努力,我终于找到了答案(在留下评论的人的帮助下。这是新的和改进的 EventsPage:

import React, { useEffect, useState } from 'react'
import BasicCard from 'pages/EventsPage/EventsCard/index'
import UpcomingEvent from 'pages/EventsPage/UpcomingEvent/UpcomingEvent'
import UpcomingShowFlyerMobile from 'assets/images/flyer-mobile.png'
import EventsHeroImage from 'assets/images/events-hero-image.jpg'
import EventsHeroImageMobile from 'assets/images/events-mobile-hero-image.jpeg'
import CountdownTimer from 'pages/EventsPage/CountdownTimer/CountdownTimer'
import { Grid } from '@material-ui/core'
import useStyles from './styles'

const EVENTS = [
  {
    month: 'AUG',
    day: '09',
    title: 'SUMMER 2019 SHOWCASE',
    time: '7:30PM-9:00PM',
    location: 'The Irenic, San Diego, CA',
  },
  {
    month: 'APR',
    day: '17',
    title: 'SPRING 2019 SHOWCASE',
    time: '7:30PM-9:00PM',
    location: 'The Irenic, San Diego, CA',
  },
  {
    month: 'AUG',
    day: '09',
    title: 'FALL 2019 SHOWCASE',
    time: '7:30PM-9:00PM',
    location: 'The Irenic, San Diego, CA',
  },
  {
    month: 'APR',
    day: '17',
    title: 'WINTER 2019 SHOWCASE',
    time: '7:30PM-9:00PM',
    location: 'The Irenic, San Diego, CA',
  },
]

const UPCOMINGEVENT = [
  {
    title: 'WINTER 2020 SHOWCASE',
    date: 'JAN 24TH',
    location: 'THE IRENIC, SAN DIEGO',
    about:
      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Consectetur cursus nunc faucibus justo enim, eget dignissim lacus turpis. Tincidunt sed mauris in volutpat. Sapien fringilla libero, facilisis elementum nisi lobortis amet porttitor. Velit risus diam sit feugiat velit enim et, euismod quis.',
  },
]
// const UPCOMINGEVENT = [
//   {
//     title: null,
//     date: null,
//     location: null,
//     about: null,
//   },
// ]

const EventsPage = () => {
  const classes = useStyles()
  const [events, setEvents] = useState(EVENTS)
  const [upcomingEvent, setUpcomingEvent] = useState(UPCOMINGEVENT)

  useEffect(() => {
    if (upcomingEvent !== null) {
      setUpcomingEvent(UPCOMINGEVENT)
    } else {
      null
    }
  }, [upcomingEvent])

  const startDate = '04/23/2021'
  const endDate = '05/04/2021'
  return (
    <div>
      {/*-------------Mobile View--------------------- */}
      <Grid
        container
        direction='column'
        justify='center'
        alignItems='center'
        spacing={0}
        className={classes.allContainerMobile}
      >
        <div className={classes.headingContainerMobile}>
          <div>
            <p className={classes.allEventsTitleMobile}>ALL EVENTS</p>
          </div>
          {upcomingEvent === null ? (
            <div>
              <div className={classes.parentDivImageMobile}>
                <div className={classes.ImageDivMobile}>
                  <img
                    src={EventsHeroImageMobile}
                    className={classes.placeHolderImageMobile}
                  />
                </div>
              </div>
            </div>
          ) : (
            <div>
              <Grid item sm={12} className={classes.gridMobile}>
                <div className={classes.countdownContainerMobile}>
                  <div className={classes.countdownParentMobile}>
                    <CountdownTimer
                      countdown={startDate}
                      unixEndDate={endDate}
                    />
                  </div>
                </div>
              </Grid>
            </div>
          )}
          {upcomingEvent === null ? (
            <div>
              <div>
                <p className={classes.upcomingShowMobile}>UPCOMING SHOW</p>
              </div>
              <div>
                <p className={classes.noUpcomingShowsMobile}>
                  NO UPCOMING SHOWS...FOR NOW.
                </p>
              </div>
            </div>
          ) : (
            <div>
              <div className={classes.flyerImageMobile}>
                <div className={classes.upcomingShowParentMobile}>
                  <img
                    src={UpcomingShowFlyerMobile}
                    className={classes.imageStyleMobile}
                  />
                </div>
              </div>
            </div>
          )}
        </div>
        {upcomingEvent !== null ? (
          <div>
            {upcomingEvent.map(({ title, date, location, about }) => (
              <UpcomingEvent
                key={title}
                title={title}
                date={date}
                location={location}
                about={about}
              />
            ))}
          </div>
        ) : null}
        {upcomingEvent === null ? (
          <div>
            <h2 className={classes.pastShowsMobile}>PAST SHOWS</h2>
          </div>
        ) : (
          <div>
            <h2 className={classes.pastShowsUpcomingMobile}>PAST SHOWS</h2>
          </div>
        )}

        <div className={classes.eventsCardMobile}>
          {events.map(({ month, day, title, time, location }, i) => (
            <BasicCard
              key={`${title}-${i}`}
              month={month}
              day={day}
              title={title}
              time={time}
              location={location}
            />
          ))}
        </div>
      </Grid>

这是 UpcomingEvent 组件:

import UpcomingShowFlyerDesktop from 'assets/images/flyer-desktop.png'
import { Grid } from '@material-ui/core'
import useStyles from '../styles'

function UpcomingEvent({ title, date, location, about }) {
  const classes = useStyles()
  return (
    <div>
      <div className={classes.upcomingShowsMobile}>
        <div className={classes.titleContainerMobile}>
          <p className={classes.upcomingShowTitleMobile}>{title}</p>
        </div>
        <div className={classes.dateLocationContainerMobile}>
          <p className={classes.upcomingShowDateLocationMobile}>
            {date} | {location}
          </p>
        </div>
        <div className={classes.aboutContainerMobile}>
          <p className={classes.aboutUpcomingShowMobile}>{about}</p>
        </div>
        <div className={classes.upcomingShowButtonContainerMobile}>
          <button className={classes.upcomingShowButtonMobile}>
            BUY TICKETS
          </button>
        </div>
      </div>
    </div>
  )
}

export default UpcomingEvent

推荐阅读