javascript - 当用户手动输入 URL 而不是通过链接输入时如何处理?

标签 javascript reactjs react-router

我有一个组件 (ContainerMain.js),它从 API 中获取容器列表,随后在按钮中呈现每个容器名称。单击其中一个按钮时,状态将使用“history.push(/containercontents/${id}, {container: container})”传递给另一个组件 (ContainerContents.js)。 当我在 ContainerMain.js 中选择一个按钮时,这会起作用。

为了处理当我手动刷新和输入 url(“http://localhost:3000/containercontents/6”)时导致 ContainerContents.js 被渲染,我使用“props.match.params.id”来获取容器的 ID 并从那里开始。

这是我所了解的,因为我不知道如何只使用一个数据源,具体取决于该数据是来自 url 还是来自按钮。那有意义吗?即使我这样做了,这个解决方案看起来也很糟糕,我觉得我缺少一种处理这种情况的明显方法。我对 Redux/Context 不是很熟悉,但我相信我可以使用其中之一来解决这个问题。我只想知道在使用 Redux/Context 之前是否有更简单、更通用的方法来处理这种情况,假设我可以使用它们来处理这个问题。

ContainerMain.js

import React, { useState, useEffect } from 'react'
import { Link, Route, useHistory } from 'react-router-dom'
import ContainerContents from './ContainerContents';

const ContainerMain = (props) => {
  const [containers, setContainers] = useState([]);
  // const [showContainerContents, setShowContainerContents] = useState(false);
  // const [selectedContainerId, setSelectedContainerId] = useState();
  const history = useHistory();
  
  const getContainers = async () => {
    const url = "/api/containers";    

    await fetch(url)
      .then(response => response.json())
      .then(response => setContainers(response))
      .catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
  }

  const deleteContainer = async (containerId) => {
    let result = window.confirm("Are you sure you want to delete your " + containers.find(container => container.id === containerId).name + "?");
    if (result) {
        setContainers(containers.filter(container => container.id !== containerId))

        fetch(`api/containers/${containerId}`, {
             method: 'DELETE',
        })
        .then(res => res.json()) // or res.json()
        .then(res => console.log(res))
    } 
    else {
        return
    }
  }


  // const onButtonClick = (containerId) => {
  //   setShowContainerContents(true)
  //   setSelectedContainerId(containerId)
  // }

  useEffect(() => {
    getContainers();  
  }, []);

  
  return (
    <div>   
      <strong>MY FOOD CONTAINERS</strong>
      <br></br><br></br>

      <ul>
        {containers.map(container => (
          <li key={container.id}>
            <div>
              <button onClick={() => deleteContainer(container.id)} className="button is-rounded is-danger">Delete</button>
              <button onClick={() => history.push(`/containercontents/${container.id}`, {container: container})} className="button is-primary">{container.name}</button>
              

              {/* <Route 
              path="/ContainerContents" component={HomePage}/> */}

              {/* <Link to={`/containercontents/${container.id}`}>{container.name}</Link> */}
              {/* <Link to={{
                  pathname: `/containercontents/${container.name}`,
                  state: {container: container}
                }}>{container.name}
              </Link> */}
            </div>
          </li>
        ))}
      </ul>  

   
      {/* {showContainerContents ? <ContainerContents containerId={selectedContainerId}  /> : null}   */}
      
      
    </div>
  );
}

export default ContainerMain;

ContainerContents.js

import React, { useEffect, useState} from 'react';

const ContainerContents = (props) => {
  const [container, setContainer] = useState({});



  useEffect(() => {
    const fetchContainer = async () => { 
      const { id } = props.match.params;

      console.log("This is the id: " + id)

      let url = `/api/containers/${id}`;
  
      await fetch(url)
        .then(response => response.json())
        .then(response => setContainer(response))
        .catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
  }

  fetchContainer();   

      
  }, [props.match.params]);



  


  
  return (
    <div>

          {/* will not work when I refresh and enter url as expected*/}
         <h1>{props.location.state.container.name}</h1> 



         <h1>{container.name}</h1> 
         

    </div>
  )
}

export default ContainerContents;

最佳答案

据我了解,您希望能够在使用该方法时从按钮点击中获取 id,而在手动访问时从 url 中获取 id。

一个简单的方法可能是在 props.match.params 不存在的情况下从 url 中检索 id?您应该能够使用 useLocation Hook 来访问它,然后我确定有一种更简单的方法,但您可以只解析您想要的 ID。

喜欢:

  const location = useLocation();

  let url_segs = location.pathname.split("/");
  let id = url_segs[url_segs.length - 1]

另外我相信 react-router-dom 现在支持 useParams如果您有兴趣,可以使用更简单的方法访问参数。

关于javascript - 当用户手动输入 URL 而不是通过链接输入时如何处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62855095/

相关文章:

javascript - React 中的状态正在返回到原始值

javascript - React Router : this. props.params 在链接单击后未更新

javascript - 为什么在我尝试调试 ASP.NET 程序时 Internet Explorer(或其他浏览器)使用旧的 JavaScript 文件?

javascript - 来自异步函数的 Webpack DefinePlugin

javascript - 向分组对象添加属性并取消分组

reactjs - 如何在 Material ui Popper 中输入过渡 Prop

javascript - WooCommerce:根据所选的运输方式显示或隐藏结账字段和部分

css - react 中的内联CSS无法动态工作

javascript - 在react-router的普通对象中转换多个配置路由

javascript - react 路由器传递数据