繁体   English   中英

在 React 组件之间共享数据

[英]Sharing data between React components

我在 React 中有一个搜索表单,它执行 API 调用并使用 useState() React 挂钩将名为名称服务器的数据保存在状态。

我正在尝试确定如何将这些数据传递给另一个组件,以便可以将数据用于在页面上的其他位置呈现。

目前,我只是在搜索表单下方显示的返回块中输出数据。

import React, { useState } from "react";
import { Spinner, Form, Button, Container, Col } from "react-bootstrap";
import { FaSearch } from "react-icons/fa";

const SearchForm: React.FC = () => {
  const [domain, setDomain] = useState("");
  const [loading, setLoading] = useState(false);
  const [nameservers, setNameservers] = useState([]);
  const [submitted, setSubmitted] = useState(false);

  const formText = "Search for a domains";

  const handleChange = (event: any) => {
    setDomain(event.target.value);
  };

  const handleSubmit = (event: any) => {
    event.preventDefault();
    setLoading(true);
    setSubmitted(true);
    console.log(domain);

    fetch(`https://dns.google.com/resolve?name=${domain}&type=NS`)
      .then(results => results.json())
      .then(data => {
        setLoading(false);
        if (data && data.Answer) {
          data.Answer.sort((a: any, b: any) => a.data.localeCompare(b.data));
          setNameservers(data.Answer);
        }
      });
  };

  return (
    <>
      <Form onSubmit={handleSubmit}>
        <Form.Row>
          <Col />
          <Col>
            <Form.Control
              type="text"
              placeholder={formText}
              value={domain}
              onChange={handleChange}
              autoFocus
              required
            />
          </Col>
          <Col>
            <Button variant="primary" type="submit">
              <FaSearch /> Search
            </Button>
          </Col>
        </Form.Row>
      </Form>
      <hr />
      {submitted &&
        nameservers.map((server: any, index: number) => (
          <li key={index}>{server.data}</li>
        ))}

      {submitted && nameservers.length === 0 && <small>Error</small>}

      {loading && (
        <Container className="text-center">
          <Spinner animation="grow" size="sm" />
          <Spinner animation="grow" size="sm" />
          <Spinner animation="grow" size="sm" />
        </Container>
      )}
    </>
  );
};

export default SearchForm;

有多种方法可以在组件之间共享数据。 您可以使用以下选项之一:

  • 如果要向其传递数据的组件是SearchForm组件的子组件,则可以将其作为prop传递。

  • If you are managing state via redux, you can connect components to the redux store and get the required data from the redux store in your components.

  • 您还可以使用 React 的Context API在可能具有或不具有父子关系的组件之间共享公共数据。

  • 如果需要SearchForm组件数据的组件是SearchForm组件的父组件,可以将回调function作为prop传递给SearchForm组件,当SearchForm组件中有数据时,调用回调function,作为prop接收,并将数据作为参数传递给该回调 function。

我会按照优素福的建议去做。

SearchForm 应该有两个道具:nameservers handleSubmit

(这将使编写 Storybook 故事和任何测试变得容易)。

然后为 SearchForm 创建一个包装器,该包装器执行 API 调用 (handleSubmit) 并在上下文中设置名称服务器。 现在可以在应用程序的其他地方访问名称服务器。

Ciao,当我想在组件之间共享数据时,我使用React-Redux 让我们举个例子:假设您要共享服务器(名称服务器)接收到的数据。 首先安装 react-redux:

npm install react-redux
npm install redux
npm install @reduxjs/toolkit

现在我们必须创建reduceraction :假设您将组件放在一个名为“/components/MyComponent”的文件夹中。 创建一个名为 MyReducer.js 的文件。

/components/MyComponent/MyReducer.js

import { createReducer } from '@reduxjs/toolkit';

const initialState = {
  nameservers: undefined,
};

const LoginReducer = createReducer(initialState, {
   ["SET_NAMESERVERS"]: (state, action) => {
       state.nameservers= action.payload.nameservers;
   },
})

export default MyReducer;

现在,在同一个文件夹中,创建一个名为 MyAction.js 的文件

/components/MyComponent/MyAction.js

export const setNameServers = data => ({
   type: "SET_NAMESERVERS",
   payload: { nameservers: data }
});

然后创建store :在您的项目根目录上创建一个redux的文件夹。 在其中创建一个名为store的文件夹。 然后在这个文件夹上创建一个名为 index.js 的文件。

redux/store/index.js

import { createStore, combineReducers } from "redux";
import MyReducer from '../../components/MyComponent/MyReducer';

const reducers = combineReducers({
  MyReducer,
});

const store = createStore(reducers);

export default store;

现在在根文件夹上的 index.js 文件中,让我们传递已经创建的商店:

index.js

...
import { Provider } from 'react-redux';
import store from "./redux/store";

ReactDOM.render((
 <Provider store={store}>
    <App />
 </Provider>
), document.getElementById('root') || document.createElement('div'));

我们几乎完成了。 在您的组件 (MyComponent) 上,您从服务器检索数据。 获得数据后,让我们将数据发送到 store 中共享

/components/MyComponent/MyComponent.js

...
import { useDispatch } from 'react-redux';
import { setNameServers } from './MyComponentAction';

const MyComponent: React.FC = () => {
   const [nameservers, setNameservers] = useState([]);
   const dispatch = useDispatch();
   ....
   const handleSubmit = (event: any) => {
     ...

fetch(`https://dns.google.com/resolve?name=${domain}&type=NS`)
.then(results => results.json())
.then(data => { 
  setLoading(false);
  if (data && data.Answer) {
    data.Answer.sort((a: any, b: any) => a.data.localeCompare(b.data));
    setNameservers(data.Answer);
    dispatch(setNameServers(data.Answer)); // here the magic
  } 
  });
 };
   
};

完成:现在您的 react redux 商店中有名称服务器,您可以轻松地从另一个组件中获取它,如下所示:

其他组件.js

import { useSelector } from 'react-redux';
const OtherComponent: React.FC = () => {
   const nameservers = useSelector(state => state.MyReducer.nameservers);
};

如果您在OtherComponent中的某处记录名称服务器,您将看到在MyComponent中检索到的数据。 惊人的!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM