簡體   English   中英

如何使用 React 正確設置 react-router-dom 鏈接

[英]How to set properly react-router-dom links with React

由於缺乏經驗,我一直在為我的第一個個人項目而苦苦掙扎,這是我遇到的麻煩:

我需要設置一個鏈接組件(react-router-dom),當我單擊按鈕時它會將我帶到另一個新頁面。 認為我需要將選擇傳遞給鏈接(和上下文)id,以便我可以從 API 獲取數據,但我不知道如何使它工作。 這是按鈕鏈接組件:

Model.jsx

import React, { useState, useContext } from 'react';
import { BrowserRouter as Router, Switch, Route, Link, Redirect } from 'react-router-dom';
import FileModel from "../FileModel/FileModel";
import { ModelsContext } from "../../context/ModelsContext";

const Model = ({modelo}) => {

    const { id, name, year, price, photo } = modelo;

    const { guardarModelo } = useContext(ModelsContext);

    const [display, setDisplay] = useState("btn-notdisplayed");
    const showButton = e => {
      e.preventDefault();
      setDisplay("btn-displayed");
    };
  
    const hideButton = e => {
      e.preventDefault();
      setDisplay("btn-notdisplayed");
    };

 

    return (   
            <div 
                className="card"
                onMouseEnter={e => showButton(e)}
                onMouseLeave={e => hideButton(e)}
            >
                <div className="card-body">
                    <p className="card-name">{name}</p>
                    <p className="card-yearprice">{year} | $ {price}</p>
                </div>
                <img src={`https://challenge.agenciaego.tech${photo}`} className="card-image" alt={`Imagen de ${name}`} />
                <Router>
                    <button 
                        type="button" 
                        className={display}
                        onClick={() => {
                            guardarModelo(modelo);
                        }}
                    ><Link to={`/models/${modelo.id}`}>Ver Modelo</Link>
                    </button>
                    <Switch>
                        <Route exact path={`/models/${modelo.id}`} component={FileModel} />
                    </Switch>
                </Router>         
            </div>   
     );
}
 
export default Model;

然后我從上下文中獲取數據:

模型上下文.jsx

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

export const ModelsContext = createContext();

const ModelsProvider = (props) => {

        //State de modelos
        const [ modelo, guardarModelo ] = useState({});
        const [ modelos, guardarModelos ] = useState([]);
        const [ allModelos, guardarAllModelo ] = useState([]);
 

         //Cargar un modelo
         useEffect(() => {
             const consultarAPI = async () => {
                

                 const api = await fetch("https://challenge.agenciaego.tech/models");
                 const modelos = await api.json();

                 const api2 = await fetch(`https://challenge.agenciaego.tech/models/${id}`);
                 const modelo = await api2.json();
                 
                 guardarAllModelo(modelos);
                 guardarModelos(modelos);
                 guardarModelo(modelo);

             }
             consultarAPI()
         }, []);

    return (
        <ModelsContext.Provider
            value={{
                allModelos,
                modelo,
                modelos,
                guardarModelo,
                guardarModelos
            }}
        >
            {props.children}
        </ModelsContext.Provider>
    )
}

export default ModelsProvider;

最后,我得到了 App.js,我從中路由主組件,這個想法是將鏈接到名為“FileModel.jsx”的新組件作為子組件,因此維護導航欄組件。

應用程序.js

import React from "react";
import Navbar from "./components/Nav/Navbar";
import Models from "./components/Models/Models";
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import Logo from "./assets/img/logo.png";
import ModelsProvider from "./context/ModelsContext";
import ModelFooter from "./components/Models/ModelFooter";

function App() {

  return (
    <ModelsProvider> 
        <Router>
            <nav className="navbar">
                <img src={Logo} className="logo" alt="Ego Logo" />
                <div className="menu-container">
                    <Link to={'/models'} className="menu-items">Modelos</Link>
                    <a className="menu-items">Ficha de modelo</a>
                </div>
                <div className="bottom-line"></div>
            </nav>
            <Switch>
              <Route exact path='/models' component={Models} />
            </Switch>
        </Router>
        <Navbar />
        <ModelFooter /> 
    </ModelsProvider>
  );
}

export default App;

到目前為止,這是 fileModel.jsx:

import React, { useContext } from 'react';
import Navbar from "../Nav/Navbar";
import { ModelsContext } from "../../context/ModelsContext";

const FileModel = () => {

    const { modelo } = useContext(ModelsContext);

    console.log(modelo.id);

    return ( 
        <Navbar />
     );
}
 
export default FileModel;

我希望能清楚地解釋我的問題,非常感謝所有有愛心的人!

干杯!

Ps:也許你可以找到一些東西來重構(我需要稍后檢查我的代碼),如果你發現類似的東西,任何幫助將不勝感激!

更新

由於 Linda 的建議,我將兩個上下文合並為一個,並更改了我之前編寫的一些代碼行,我無法設置 state 將單獨的 model 傳遞給 fileModel 組件並且鏈接仍然無法正常工作,我在想一個函數可以做到,我制作了另一個 state,一個單獨的模型,但是當我單擊按鈕時出現錯誤並且未定義,因為 Idk 如何在 state 中設置 Id,然后將其傳遞給 ZDB974238714CA8DE634A id in const api2 = await fetch( https://challenge.agenciaego.tech/models/${id} ); 沒有定義。

我終於解決了我的問題,我不得不在我的組件之間重新定位一些元素,以使 api 上下文獲取 id 並將其傳遞給 FileModel 組件:並將 Link 路由器更改為 App.js,這就是我得到的解決方案:

應用程序.js

import React from "react";
import Navbar from "./components/Nav/Navbar";
import Models from "./components/Models/Models";
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import Logo from "./assets/img/logo.png";
import ModelsProvider from "./context/ModelsContext";
import ModelFooter from "./components/Models/ModelFooter";
import FileModel from "./components/FileModel/FileModel";


function App() {

  return (
    <ModelsProvider> 
        <Router>
            <nav className="navbar">
                <img src={Logo} className="logo" alt="Ego Logo" />
                <div className="menu-container">
                    <Link to={'/models'} className="menu-items">Modelos</Link>
                    <Link to={`/models/1`} className="menu-items">Ficha del Modelo</Link>
                </div>
                <div className="bottom-line"></div>             
            </nav>
            <Switch>
              <Route exact path='/models' component={Models} />
              <Route exact path='/models' component={Models} />
            </Switch>
        </Router>
        <Navbar />
        <FileModel />
        <ModelFooter />
    </ModelsProvider>
  );
}

export default App;

模型上下文.jsx

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

export const ModelsContext = createContext();

const ModelsProvider = (props) => {

        //State de modelos
        const [ modelo, guardarModelo ] = useState([]);
        const [ modelos, guardarModelos ] = useState([]);
        const [ allModelos, guardarAllModelo ] = useState([]);

        
        const { id } = modelo;

         //Cargar un modelo
         useEffect(() => {
             const consultarAPI = async () => {
                

                 const api = await fetch("https://challenge.agenciaego.tech/models");
                 const modelos = await api.json();

                 const api2 = await fetch(`https://challenge.agenciaego.tech/models/${id}`);
                 const modelo = await api2.json();
                 
                 guardarAllModelo(modelos);
                 guardarModelos(modelos);
                 guardarModelo(modelo);

             }
             consultarAPI()
         }, [modelo.id]);

    return (
        <ModelsContext.Provider
            value={{
                allModelos,
                modelo,
                modelos,
                guardarModelo,
                guardarModelos
            }}
        >
            {props.children}
        </ModelsContext.Provider>
    )
}

export default ModelsProvider;

Model.js

import React, { useState, useContext } from 'react';
import { Link } from 'react-router-dom';
import { ModelsContext } from "../../context/ModelsContext";


const Model = ({modelo}) => {

    const { name, year, price, photo } = modelo;

    const { guardarModelo } = useContext(ModelsContext);

    const [display, setDisplay] = useState("btn-notdisplayed");
    const showButton = e => {
      e.preventDefault();
      setDisplay("btn-displayed");
    };
  
    const hideButton = e => {
      e.preventDefault();
      setDisplay("btn-notdisplayed");
    };

    return (   
            <div 
                className="card"
                onMouseEnter={e => showButton(e)}
                onMouseLeave={e => hideButton(e)}
            >
                <div className="card-body">
                    <p className="card-name">{name}</p>
                    <p className="card-yearprice">{year} | $ {price}</p>
                </div>
                <img src={`https://challenge.agenciaego.tech${photo}`} className="card-image" alt={`Imagen de ${name}`} />
                    <Link to={`/models/${modelo.id}`}><button 
                        type="button" 
                        className={display}
                        onClick={() => {
                            guardarModelo(modelo);
                        }}
                    >Ver Modelo
                    </button></Link>
            </div>   
     );
}
 
export default Model;

FileModel.js (到目前為止...)

import React, { useContext } from 'react';
import Navbar from "../Nav/Navbar";
import { ModelsContext } from "../../context/ModelsContext";

const FileModel = () => {

    const { modelo } = useContext(ModelsContext);

    const { photo, name } = modelo;

    return (
        <> 
        <Navbar />
        <section>
            <img src={`https://challenge.agenciaego.tech${photo}`} alt={`Imagen de ${name}`}/>
        </section>
        </>
     );
}
 
export default FileModel;

感謝 Linda 為我提供重構上下文的意見! 干杯!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM