首页 > 解决方案 > 当用户手动输入URL而不是通过链接时如何处理?

问题描述

我有一个组件(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;

标签: javascriptreactjsreact-router

解决方案


据我了解,您希望能够在使用该方法时从按钮单击中获取 id,并在手动到达时从 url 中获取 id。

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

像:

  const location = useLocation();

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

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


推荐阅读