【问题标题】:useHistory() react hook doesn't seem to trigger re-renderuseHistory() 反应钩子似乎不会触发重新渲染
【发布时间】:2021-11-10 22:50:58
【问题描述】:

我正在制作一个像应用程序一样的 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() 钩子重定向到的详细信息页面。请记住,如果我将 bannerDetail 添加为 useEffect 挂钩中的依赖项,它将起作用,但随后我将创建一个无限循环,

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>

【问题讨论】:

  • 检查一下stackoverflow.com/a/67612032/7077417,看看这是否有帮助我认为您可能正在处理类似的问题
  • @danwebb 我正在使用 BrowserRouter 方法我像这样 在线程中包装了 index.js你提供他们也使用基于类的组件

标签: reactjs react-router-dom


【解决方案1】:

我认为您遇到的问题是您正在分派一个 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 块。

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
  }
}

【讨论】:

  • 非常感谢你写的一切都有意义并解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多