如何将数据从一个组件发送到另一个具有反应上下文的组件?

how to send data From one component to another components with context in react?

我需要将 selectedCoin 状态从 Company 发送到 details.js 如何使用 context?

执行此操作

公司组成部分:

import React, { useState, useEffect } from "react";
import { Col, Image, Row } from "react-bootstrap";
import "./Company.scss";

// * api
import { getCoin } from "../services/api";

// *spinner
import Loader from "./Loader";

const Company = () => {
  const [selectedCoin, setSelectedCoin] = useState(null);
  const [coins, setCoins] = useState([]);

  useEffect(() => {
    const fetchAPI = async () => {
      const data = await getCoin();
      setCoins(data);
    };
    fetchAPI();
  }, []);

  const coinId = () => {
    console.log(selectedCoin);
  };

  coinId();

  return (
    <>
      {coins.length > 0 ? (
        coins.map((coin) => (
          <Row
            className={
              selectedCoin === coin.id
                ? "p-2 pe-3 border-top d-flex align-items-center company-list-single-active"
                : "p-2 border-top d-flex align-items-center company-list-single"
            }
            onClick={() => {
              setSelectedCoin(coin.id);
              // console.log(coin.id);
              // console.log(coin.name);
            }}
            key={coin.id}
          >
            <Col xxl="2" xl="2" lg="3" md="3" sm="2" xs="2">
              <Image
                src={coin.image}
                alt={coin.name}
                className="coin-image mx-2"
                fluid
              />
            </Col>
            <Col>
              <span>{coin.name}</span>
            </Col>
          </Row>
        ))
      ) : (
        <Loader />
      )}
    </>
  );
};
export default Company;

详细组件:

import React, { useState, useEffect } from "react";
import axios from "axios";

const Details = () => {
  const [data, setData] = useState({
    name: "",
    id: "",
  });

  const apiDetails = async () => {
    await axios
      .get(`https://api.coingecko.com/api/v3/coins/${"ethereum"}`)
      .then((r) => {
        // console.log(response);
        setData({
          name: r.data.name,
          id: r.data.id,
        });
        return setData;
      });
  };

  useEffect(() => {
    (async () => {
      const response = await apiDetails();
      setData({
        name: response.data.name,
        id: response.data.id,
      });
    })();
  }, []);

  return (
    <div>
      <h1>{data.name}</h1>
      <h1>{data.id}</h1>
    </div>
  );
};

export default Details;

您只需要创建上下文的包装器。这个包装器只是一个组件,它的状态将作为上下文的值传递,以便您可以在任何需要的地方对其进行编辑。

这是一个简单的示例,说明如何实现上下文以在组件之间共享数据:

import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';

const MyContext = React.createContext();
const MyContextProvider = (props) => {
  const [data, setData] = React.useState('Initial value');

  return (
    <MyContext.Provider value={{ data, setData }}>
      {props.children}
    </MyContext.Provider>
  );
};

const App = () => {
  return (
    <MyContextProvider>
      <Component1 />
      <hr />
      <Component2 />
    </MyContextProvider>
  );
};

const Component1 = () => {
  const { data, setData } = React.useContext(MyContext);
  return (
    <>
      [component 1] data = {data}
      <br />
      <button onClick={() => setData('data written from component 1')}>
        Update context
      </button>
    </>
  );
};

const Component2 = () => {
  const { data, setData } = React.useContext(MyContext);
  return (
    <>
      [component 2] data = {data}
      <br />
      <button onClick={() => setData('data written from component 2')}>
        Update context
      </button>
    </>
  );
};

render(<App />, document.getElementById('root'));

这里是 Stackblitz.

嗯,看起来你只是对代码感兴趣,所以我就把代码放在这里。 显然,可以随意移动代码并确保使用对您有意义的语法

这是上下文

CoinsContext.js

import React, { createContext, useContext, useState, useEffect } from "react";
import { getCoin } from "@api";

const CoinsContext = createContext({});

export const CoinsContextProvider = ({ children }) => {
  const [selectedCoin, setSelectedCoin] = useState(null);
  const [coins, setCoins] = useState([]);

  useEffect(() => {
    const fetchAPI = async () => {
      const data = await getCoin();
      setCoins(data);
    };
    fetchAPI();
  }, []);

  return (
    <CoinsContext.Provider value={{ selectedCoin, setSelectedCoin, coins }}>
      {children}
    </CoinsContext.Provider>
  );
};

export const useCoins = () => useContext(CoinsContext);

要使用它,您需要将所有要使用它的上下文的页面包装起来,例如,因为您想要 Details.js 和 Company.js 使用它,您将需要用它包裹两页。 我只是把整个 App 包装起来,这意味着整个 App 都可以使用它,但是你可以随意做你想做的事情。

会是这样的:

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

import { CoinsContextProvider } from "./CoinsContext";

ReactDOM.render(
  <React.StrictMode>
    <CoinsContextProvider>
      <App />
    </CoinsContextProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

现在我们已经设置了 CoinsContext,我们可以在您的组件上使用它

Company.js

import React from "react";
import { Col, Image, Row } from "react-bootstrap";
import "./Company.scss";

// *spinner
import Loader from "./Loader";
import { useCoins } from "./CoinsContext";

const Company = () => {
  const { coins, selectedCoin, setSelectedCoin } = useCoins();

  return (
    <>
      {coins.length > 0 ? (
        coins.map((coin) => (
          <Row
            className={
              selectedCoin === coin.id
                ? "p-2 pe-3 border-top d-flex align-items-center company-list-single-active"
                : "p-2 border-top d-flex align-items-center company-list-single"
            }
            onClick={() => {
              setSelectedCoin(coin.id);
              // console.log(coin.id);
              // console.log(coin.name);
            }}
            key={coin.id}
          >
            <Col xxl="2" xl="2" lg="3" md="3" sm="2" xs="2">
              <Image
                src={coin.image}
                alt={coin.name}
                className="coin-image mx-2"
                fluid
              />
            </Col>
            <Col>
              <span>{coin.name}</span>
            </Col>
          </Row>
        ))
      ) : (
        <Loader />
      )}
    </>
  );
};
export default Company;

Details.js

import React, { useState, useEffect } from "react";
import axios from "axios";

import { useCoins } from "./CoinsContext";

const Details = () => {
  const { selectedCoin, coins, setSelectedCoin } = useCoins();
  
  const [data, setData] = useState({
    name: "",
    id: "",
  });


  const apiDetails = async () => {
    await axios
      .get(`https://api.coingecko.com/api/v3/coins/${"ethereum"}`)
      .then((r) => {
        // console.log(response);
        setData({
          name: r.data.name,
          id: r.data.id,
        });
        return setData;
      });
  };

  useEffect(() => {
    (async () => {
      const response = await apiDetails();
      setData({
        name: response.data.name,
        id: response.data.id,
      });
    })();
  }, []);

  return (
    <div>
      <h1>{data.name}</h1>
      <h1>{data.id}</h1>
    </div>
  );
};

export default Details;

大功告成!现在您不仅在您的组件之间共享 selectedCoin,而且您还将所有硬币获取逻辑放在您的上下文中,总体而言这是正确的做法