reactjs - useHistory() react 钩子(Hook)似乎没有触发重新渲染

标签 reactjs react-router-dom

我正在制作一个类似于应用程序的 CRUD 博客,当我发布或编辑博客时,我使用 history.push() 重定向用户,但是当用户被重定向时,如果我刷新页面,信息仍然是旧的,内容被更新.在过去的一天里,我到处都在寻找,但我似乎找不到问题的答案。例如,这是我更新信息的组件

import { useState, useEffect, useRef } from "react";
import { useParams, useHistory } from "react-router";

const EditBanner = (props) => {


 const [imgValue, setImgValue] = useState('');
 const [descriptionValue, setDescriptionValue] = useState('');


 const params = useParams();
 const history = useHistory();

 const imgRef = useRef();
 const descriptionRef = useRef();

  useEffect(() => {
      const fetchBlog = async () => {
          const response = await fetch(`URL/banners/${params.id}.json`);
          const data = await response.json();
          setImgValue(data.img);
          setDescriptionValue(data.description);

      }

      fetchBlog();
  },[params])

    const onSubmitHandler = (e) => {

        e.preventDefault()

        fetch(`URL/banners/${params.id}.json`,{
            method: "PUT",
            body: JSON.stringify({
                description: descriptionRef.current.value,
                img: imgRef.current.value
            }),
            headers: {
                'Content-Type': 'application/json'
            }
        })

        history.push(`/banners/${params.id}`);
    }

    const imgUrlChangeHandler = () => {
        setImgValue(imgRef.current.value)
    }
    const descriptionChangeHandler = () => {
        setDescriptionValue(descriptionRef.current.value)
    }




    return (
        <form onSubmit={onSubmitHandler}>
            <input type="text" placeholder="img url" ref={imgRef} value={imgValue} onChange={imgUrlChangeHandler}></input>
            <textarea ref={descriptionRef} value={descriptionValue} onChange={descriptionChangeHandler}></textarea>
            <button>Submit</button>
        </form>
    )
}

export default EditBanner;

这是我使用 useHistory() Hook 重定向到的详细信息页面。请记住,如果我将 bannerDetail 作为依赖项添加到 useEffect Hook 中,它会起作用,但随后我将创建一个无限循环,

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

import styles from './BannerDetail.module.css';

const BannerDetail = (props) => {
    const history = useHistory();
    const params = useParams();
    const [bannerDetail, setBannerDetail] = useState({});

    useEffect(() => {
        const fetchBanner = async () => {
            const response = await fetch(`URL/banners/${params.id}.json`);
            const data = await response.json();
            console.log(data)
            setBannerDetail(data);
        }
        console.log('useEffect run in bannerDetail')
        fetchBanner();
    },[params])


    const onEditHandler = (e) => {
        e.preventDefault();
        history.push(`/banners/${params.id}/edit`)
    }
    const onDeleteHandler = (e) => {
        e.preventDefault();
        fetch(`URL/banners/${params.id}.json`,{
            method: "DELETE",
            headers: {
                'Content-Type': 'application/json'
              }
        })

        history.replace('/banners')
    }



    return (
        <section className={styles.detail}>
            <div className={styles['image-container']}>
                <img
                    src={bannerDetail.img}
                    alt={bannerDetail.description}
                />
            </div>
            <div className={styles['description-container']}>
                <p>{bannerDetail.description}</p>
            </div>
            <div className={styles.actions}> 
                <button onClick={onEditHandler}>Edit</button>
                <button onClick={onDeleteHandler}>Delete</button>
            </div>

        </section>
    )
}


export default BannerDetail;

这里还有我所有的路线,

<Switch>
  <Route path="/" exact><Redirect to="/banners"/></Route>

  <Route path="/banners" exact> <Banners/> </Route>

  <Route path="/new-banner" exact>
    <AddNewUser/>
  </Route>

  <Route path="/banners/:id/edit" exact>
    <EditBanner/>
  </Route>

  <Route path="/banners/:id" >
    <BannerDetail/>
  </Route>
</Switch>

最佳答案

我认为您遇到的问题是您正在分派(dispatch) PUT 请求,然后立即导航到新页面,在该页面上组件安装时发出 GET 请求。无法保证网络请求的解析顺序。

在导航到下一页之前,您可能希望先等待 PUT 请求解决。

const onSubmitHandler = (e) => {
  e.preventDefault();

  fetch(`URL/banners/${params.id}.json`,{
    method: "PUT",
    body: JSON.stringify({
      description: descriptionRef.current.value,
      img: imgRef.current.value
    }),
    headers: {
      'Content-Type': 'application/json'
    }
  }).finally(() => {
    // regardless of fetch resolve/reject, navigate to new page
    history.push(`/banners/${params.id}`);
  });
}

也许在这里你可能只想在 fetch 解析时导航到下一页,或者只有 200OK 响应或者你有什么,使用 .then为此阻止。也许您想处理被拒绝的响应以向用户显示错误消息,为此使用 .catch block 。

const onSubmitHandler = (e) => {
  e.preventDefault();

  fetch(`URL/banners/${params.id}.json`,{
    method: "PUT",
    body: JSON.stringify({
      description: descriptionRef.current.value,
      img: imgRef.current.value
    }),
    headers: {
      'Content-Type': 'application/json'
    }
  })
    .then((response) => {
      if (response.ok) throw new Error('response not ok');
      history.push(`/banners/${params.id}`);
    })
    .catch(error => {
      // handle errors
    });
}

如果你更喜欢 async/await 而不是 Promise 链:

const onSubmitHandler = async (e) => {
  e.preventDefault();

  try {
    const response = await fetch(`URL/banners/${params.id}.json`,{
      method: "PUT",
      body: JSON.stringify({
        description: descriptionRef.current.value,
        img: imgRef.current.value
      }),
      headers: {
        'Content-Type': 'application/json'
      }
    });

    if (response.ok) throw new Error('response not ok');
    history.push(`/banners/${params.id}`);
  } catch(error) {
    // handle errors
  }
}

关于reactjs - useHistory() react 钩子(Hook)似乎没有触发重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69200049/

相关文章:

javascript - HighCharts 中的绘图线重叠 || react Highcharts || Y轴间隔

javascript - Material-UI:以编程方式触发悬停效果

reactjs - Expo 应用程序中的 Firebase 无密码电子邮件身份验证错误

javascript - 如何在 react router dom 中将不存在的路由重定向到主页?

javascript - 外部 Javascript 在 react.js 中不起作用

reactjs - 用 Jest 模拟react-router-dom useHistory和其他钩子(Hook)

javascript - React Router 链接重新加载页面 : Conflict with external event

javascript - 从 App.js 导航到 Places.js

javascript - 如何在没有引用的情况下复制 react 状态?

javascript - react 大日历错误 : Element type is invalid: expected a string (for built-in components)