【问题标题】:How to re-render component when useParams route changes?useParams 路由更改时如何重新渲染组件?
【发布时间】:2022-11-12 09:23:29
【问题描述】:

我正在开发一个项目,当路线匹配时,我的 PlanetDescription 组件会显示与指定路线匹配的行星,用户可以使用三个按钮更新内容。我在更改路线和更新星球内容时遇到问题,例如,使用下拉菜单从地球切换到火星,内容不会立即更新。它仅在单击三个按钮之一时更新。但是,如果我通过手动将路由键入 url 来更改路由,一切都会按预期进行。我试图寻找使用 useEffect 的解决方案,但我没有找到任何有用的东西。当 url 参数更改时,有没有一种方法可以强制组件重新呈现?我也是新手,所以感谢您的帮助!这是我正在使用的代码:

import React, { useReducer, useState, useEffect } from 'react'
import { Link } from 'react-router-dom'

// styles
import './PlanetDescription.scss'

const ACTIONS = {
  OVERVIEW: 'OVERVIEW',
  STRUCTURE: 'STRUCTURE',
  SURFACE: 'SURFACE',
}

function PlanetDescription({ planetData }) {
  const [themeColor, setThemeColor] = useState(null)

  useEffect(() => {
    setThemeColor(planetData.theme)
  }, [planetData.theme])

  const infoReducer = (state, actions) => {
    switch (actions.type) {
      case ACTIONS.OVERVIEW:
        return {
          ...state,
          planetImg: planetData.images.planet,
          planetDesc: planetData.overview.content,
          planetWiki: planetData.overview.source,
        }

      case ACTIONS.STRUCTURE:
        return {
          ...state,
          planetImg: planetData.images.internal,
          planetDesc: planetData.structure.content,
          planetWiki: planetData.structure.source,
        }
      case ACTIONS.SURFACE:
        return {
          ...state,
          planetImg: planetData.images.planet,
          planetImgOverlay: planetData.images.geology,
          planetDesc: planetData.geology.content,
          planetWiki: planetData.geology.source,
        }
      default:
        return state
    }
  }

  const [state, dispatch] = useReducer(infoReducer, {
    planetImg: planetData.images.planet,
    planetDesc: planetData.overview.content,
    planetWiki: planetData.overview.source,
  })

  const [overviewActive, setOverviewActive] = useState(true)
  const [structureActive, setStructureActive] = useState(false)
  const [surfaceActive, setSurfaceActive] = useState(false)

  const updateOverview = (e) => {
    setOverviewActive(true)
    setStructureActive(false)
    setSurfaceActive(false)
    dispatch({
      type: ACTIONS.OVERVIEW,
    })
  }
  const updateStructure = (e) => {
    setOverviewActive(false)
    setStructureActive(true)
    setSurfaceActive(false)
    dispatch({
      type: ACTIONS.STRUCTURE,
    })
  }
  const updateSurface = (e) => {
    setOverviewActive(false)
    setStructureActive(false)
    setSurfaceActive(true)
    dispatch({
      type: ACTIONS.SURFACE,
    })
  }

  console.log(state.planetWiki)

  return (
    <main className="main">
      <div className="main__btn-container">
        <button
          style={
            overviewActive ? { borderBottom: `2px solid ${themeColor}` } : {}
          }
          onClick={updateOverview}
          className="main__btn"
        >
          Overview
        </button>
        <button
          style={
            structureActive ? { borderBottom: `2px solid ${themeColor}` } : {}
          }
          onClick={updateStructure}
          className="main__btn"
        >
          Structure
        </button>
        <button
          style={
            surfaceActive ? { borderBottom: `2px solid ${themeColor}` } : {}
          }
          onClick={updateSurface}
          className="main__btn"
        >
          Surface
        </button>
      </div>
      <div className="main__img-container">
        <img
          className="main__planet-img"
          width={planetData.mWidth}
          src={state.planetImg}
          alt={state.planetName}
        />
        <img
          className={
            surfaceActive
              ? 'main__planet-overlay main__planet-overlay--active'
              : 'main__planet-overlay'
          }
          src={state.planetImgOverlay}
          alt=""
        />
      </div>
      <h1 className="main__planet-name">{planetData.name}</h1>
      <p className="main__planet-desc">{state.planetDesc}</p>
      <a
        href={state.planetWiki}
        target="_blank"
        rel="noreferrer"
        className="main__planet-wiki"
      >
        Source: <span>Wikipedia</span>
      </a>
      <section className="main__data-container">
        <div className="main__data-box">
          <p className="main__data-type">Rotation Time</p>
          <span className="main__data-value">{planetData.rotation}</span>
        </div>
        <div className="main__data-box">
          <p className="main__data-type">Revolution Time</p>
          <span className="main__data-value">{planetData.revolution}</span>
        </div>
        <div className="main__data-box">
          <p className="main__data-type">Radius</p>
          <span className="main__data-value">{planetData.radius}</span>
        </div>
        <div className="main__data-box">
          <p className="main__data-type">Average Temp.</p>
          <span className="main__data-value">{planetData.temperature}</span>
        </div>
      </section>
    </main>
  )
}

export default PlanetDescription

//

import React, { useEffect } from 'react'
import { useParams } from 'react-router-dom'

// data
import data from '../../data/data.json'

// components
import PlanetDescription from '../../components/PlanetDescription/PlanetDescription'

function Planet() {
  
  const { planetId } = useParams()
  const planetData = data.find(
    (planet) => planet.name.toLowerCase() === planetId
  )

  return (
    <React.Fragment>
      <PlanetDescription planetData={planetData} />
    </React.Fragment>
  )
}

export default Planet

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:
    import React, { useEffect, useState } from 'react'
    import { useParams } from 'react-router-dom'
    
    // data
    import data from '../../data/data.json'
    
    // components
    import PlanetDescription from '../../components/PlanetDescription/PlanetDescription'
    
    function Planet() {
      const [planetData, setPlanetData] = useState({});
      const { planetId } = useParams();
    
      const getPlanetData = () => data.find(
        (planet) => planet.name.toLowerCase() === planetId
      )
    
      useEffect(()=> {
        setPlanetData(getPlanetData())
      },[planetId])
    
      return (
        <React.Fragment>
          <PlanetDescription planetData={planetData} />
        </React.Fragment>
      )
    }
    
    export default Planet
    

    【讨论】:

      猜你喜欢
      • 2019-06-04
      • 1970-01-01
      • 2021-08-13
      • 2020-01-02
      • 1970-01-01
      • 2018-12-04
      • 1970-01-01
      • 2019-06-23
      • 2021-10-02
      相关资源
      最近更新 更多