在 React 组件之间共享数据

IT技术 javascript reactjs jsx
2021-05-22 23:28:47

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

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

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

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;
3个回答

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

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

  • 如果您通过 redux 管理状态,则可以将组件连接到 redux 存储并从组件中的 redux 存储中获取所需的数据。

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

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

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

SearchForm 应该有两个props: 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 文件上让我们通过已经创建的商店:

索引.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) 上,您从服务器检索数据。获得数据后,让我们分派数据以共享到商店中

/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. 惊人的!