【问题标题】:Why is the content removed after page refresh?为什么页面刷新后内容会被删除?
【发布时间】:2022-01-19 15:09:08
【问题描述】:

我写了两个不同的函数,它们的工作方式应该非常相似。当主要元素发生变化时(我猜),“剧集”内容每次都会获取数据,因此速度较慢。另外两个,“字符”和“位置”元素在开头获取数据,仅此而已。 现在困扰我的是,当我刷新页面或在搜索栏中手动写一些“id”时,比如 episodes/5,然后它不会加载那个 episode/5,它只能在点击链接时工作。所以整个剧集列表都在那里,但第 5 集不会自动加载。但是,通过其他两个元素,就不存在这样的问题 我希望我的意思很清楚。

Main.js

import './main.css';
import { Routes, Route, Navigate } from 'react-router-dom';
import { useState, useEffect } from 'react';
import Episodes from '../Episodes/Episodes';
import Characters from '../Characters/Characters';
import Character from '../Character/Character';
import Locations from '../Locations/Locations';
import Location from '../Location/Location';
import Home from '../Home/Home';

export default function Main() {
  const [characters, setCharacters] = useState([]);
  const [locations, setLocations] = useState([]);

  useEffect(() => {
    (async function () {
      const resp = await fetch('https://rickandmortyapi.com/api/character');
      const data = await resp.json();
      setCharacters(data.results);
    })();
  }, []);

  useEffect(() => {
    (async function () {
      const resp = await fetch('https://rickandmortyapi.com/api/location');
      const data = await resp.json();
      setLocations(data.results);
    })();
  }, []);

  return (
    <div className='mainContent'>
      <Routes>
        <Route path='/' element={<Home />} />
        <Route path='/episodes/*' element={<Episodes />} />
        <Route path='/characters/*' element={<Characters list={characters} />} />
        <Route path='/locations/*' element={<Locations list={locations} />} />
        <Route path='*' element={<Navigate to='/' />} />
      </Routes>

      <Routes>
        <Route path='/characters/:id' element={<Character list={characters} />} />
        <Route path='/locations/:id' element={<Location list={locations} />} />
      </Routes>
    </div>
  );
}

Episodes.js

import './episodes.css';
import Episode from '../Episode/Episode';
import { Routes, Route, useLocation, NavLink } from 'react-router-dom';
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';

export default function Episodes() {
  const [episodes, setEpisodes] = useState([]);

  useEffect(() => {
    (async function () {
      const resp = await fetch('https://rickandmortyapi.com/api/episode');
      if (!resp.ok) throw new Error('No Episodes');
      const data = await resp.json();
      setEpisodes(data.results);
    })();
  }, []);

  function findEpisode(id) {
    return episodes.find((item) => +id === item.id);
  }
  return (
    <>
      <div className='results'>
        <h2>Episodes List</h2>
        {episodes.length === 0 && <p>No Episodes...</p>}
        {episodes.map((item) => (
          <p key={item.name}>
            <NavLink className='activeNavLink' to={`/episodes/${item.id}`}>
              {item.name}
            </NavLink>
          </p>
        ))}
      </div>

      <div className='details'>
        <Routes>
          <Route path='/:id' element={<Episode findEpisode={findEpisode} />}></Route>
        </Routes>
      </div>
    </>
  );
}

Episode.js(刷新页面或手动重写url后不会加载)

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

export default function Episode({ findEpisode }) {
  const [episode, setEpisode] = useState(null);
  const { id } = useParams();
  console.log(id);

  useEffect(() => {
    setEpisode(findEpisode(id));
  }, [id]);

  let details = (
    <>
      <p>{episode && episode.name}</p>
      <p>{episode && episode.episode}</p>
      <p>{episode && episode.air_date}</p>
    </>
  );
  return (
    <>
      <h2>Episode Details</h2>
      {episode && details}
    </>
  );
}

Characters.js

import './characters.css';
import { NavLink } from 'react-router-dom';

export default function Characters({ list }) {
  return (
    <>
      <div className='results'>
        <h2>Characters List</h2>
        {list.length === 0 && <p>No character...</p>}
        {list.map((item, index) => (
          <p key={item.name}>
            <NavLink className='activeNavLink' to={`/characters/${item.id}`}>
              {item.name}
            </NavLink>
          </p>
        ))}
      </div>
    </>
  );
}

Character.js

import { useParams } from 'react-router-dom';

export default function Character({ list }) {
  let params = useParams();
  const id = params.id;
  console.log(id, list);
  const character = list.find((char) => +char.id === +id);
  console.log(character);
  if (!character || !id) return '';
  return (
    <div className='charInfo'>
      <h2>Character Details</h2>
      <div className='charImage'>
        <img src={character.image} alt='Logo' />
      </div>
      <p>{character.name}</p>
    </div>
  );
}

【问题讨论】:

  • 加载页面episodes/5时会得到什么?我的猜测是您的网络服务器返回一个 404,而它实际上应该为 all 请求返回相同的索引页面。
  • 它给了我像 Episode.js 中写的那样的“剧集细节”,但是没有 details,比如 &lt;p&gt;{episode &amp;&amp; episode.name}&lt;/p&gt; &lt;p&gt;{episode &amp;&amp; episode.episode}&lt;/p&gt; &lt;p&gt;{episode &amp;&amp; episode.air_date}&lt;/p&gt; ,我猜就没有 episode 对象

标签: javascript reactjs react-hooks react-router react-router-dom


【解决方案1】:

这可能是问题所在:findEpisode 函数需要在您的依赖数组中,以便在 Episode.js 上调用 useEffect

useEffect(() => {
  setEpisode(findEpisode(id));
}, [id,findEpisode]);

否则,您可能会卡在之前对具有 episodes === []findEpisode 函数的引用。

function findEpisode(id) {
  return episodes.find((item) => +id === item.id);
}

不确定它是否能解决您的问题,但这绝对是您需要解决的问题。

【讨论】:

  • 我添加了 findEpisode 函数,它可以工作:)。谢谢!但我发誓我不明白为什么我需要它。那么,在依赖项中我放置了变量,当它发生变化时,useEffect 函数将被触发对吗?如果可以的话,能不能详细解释一下?
  • 看看docs。但这与您的 findEpisode 函数在每次渲染时都从头开始重新创建这一事实有关。并且由于它使用state(episodes)对象,如果你不将它添加到依赖数组中,你的效果将从之前的渲染中执行一个“旧”版本的函数,其中episodes等于@987654332 @。您还可以完全删除依赖项数组(然后您将在每个渲染上重新运行效果)。但使用它是一个好习惯。
猜你喜欢
  • 2013-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-01
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
相关资源
最近更新 更多