Warm tip: This article is reproduced from serverfault.com, please click

Communication between two components using ReactJS

发布于 2020-11-27 23:58:20

I'm having trouble communicating between two components using React.

Here are the codes:

File Search.js:

const Search = (props) => {
  const [items, setItems] = React.useState(null);
  const [input, setInput] = React.useState("");

  const apiKey = "*********";

  async function handleSubmit(event) {
    event.preventDefault();

    await fetch(
      `https://geo.ipify.org/api/v1?apiKey=${apiKey}&ipAddress=${input}`
    )
      .then((response) => {
        console.log(response);
        return response.json();
      })
      .then((result) => {
        console.log(result);
        setItems(result);
      });
  }

  const handleChange = (event) => {
    setInput(event.target.value);
  };

  return (
    <div>
      <form onSubmit={handleSubmit} className="my-wrap">
        <input
          type="text"
          className="searchTerm"
          placeholder="Search for any IP adress or domain"
          value={input}
          onChange={handleChange}
        />
        <button type="submit" className="searchButton">
          {" "}
          <img src={RightIcon} alt="icon" />{" "}
        </button>
      </form>
    </div>
  );
};

export default Search;

File Results.js:

const Results = (props) => {
  const { ip, city, country, postalCode, timezone, isp } = props;

  return (
    <div>
      <div className="grid-container2">
        <div className="container-pop">
          <div>
            <h2 className="title-span"> IP Address </h2>
            <p> {ip} </p>
          </div>
          <div>
            <h2 className="title-span"> Location </h2>

            <p>
              {city}, {country}
            </p>

            <p> {postalCode} </p>
          </div>

          <div>
            <h2 className="title-span"> Timezone </h2>
            <p> UTC {timezone} </p>
          </div>

          <div>
            <h2 className="title-span"> ISP </h2>
            <p> {isp} </p>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Results;

What I am not able to do is the communication between them, for example: I do the Google IP search 8.8.8.8, the console returns me all right with the information, but I can't pass this information to Results.js, to take them and print them on canvas. If I do it in the same component (Search.js) it comes out on the screen, but the styling of the CSS gets messy. Is there a way to make this communication between these two components?

current output

expected output

Questioner
Adriel Gama
Viewed
0
Matthew Brooks 2020-11-28 08:39:24

Without seeing more code, I can't be 100% sure here, but it looks like what you need to do is lift your items state to a parent of <Search> and <Results>

function SearchPage() {
  const [results, setResults] = React.useState([])
  return (
    <div>
      <Search onChange={setResults) />
      <div>
        {results.map((result) => <Results {...result} />)}
      </div>
    </div>
  )
}

And you'll need to change Search.js

const Search = (props) => {
  // New prop! This is a change handler passed from the parent
  const { onChange } = props
  // remove the results data from state here
  const [input, setInput] = React.useState("");

  const apiKey = "*********";

  async function handleSubmit(event) {
    event.preventDefault();

    await fetch(
      `https://geo.ipify.org/api/v1?apiKey=${apiKey}&ipAddress=${input}`
    )
      .then((response) => {
        console.log(response);
        return response.json();
      })
      .then((result) => {
        console.log(result);
        // Instead of setting state, we call the change handler function.
        onChange(result);
      });
  }

  const handleChange = (event) => {
    setInput(event.target.value);
  };

  return (
    // ... same return value
  );
};

export default Search;

Of course, you'll need to put this in the correct markup so that it's styled the way you'd like, but the important thing here is that we took the state from Search and we lifted it a common parent of both Search and Results. This is a very common technique in React. From the common parent, we can pass a change handler to Search so that we get the results of the API request after a user inputs something, and then we can set that as state to our parent component. From there, we can pass it down into Results. This is the way with React: data flows down as props, and you pass change handler functions as props to get data back up from child components.

<SearchPage> {/* <---- put the state at this level. the next highest above Search and Results, so you can pass change handlers and data (props) _down_ into the components. */}
  <Search />
  <Results />
  <Results />
  <Results />
  <Results />
</SearchPage>