Как присвоить значение onClick из другого компонента другому компоненту в React - PullRequest
1 голос
/ 19 июня 2020

Что я хочу сделать:

  • Когда я нажимаю кнопку, т.е. Search in Navbar.js, я хочу назначить текст для поиска в переменной urlQuery, чтобы я мог передать его как props в Episodes.js компоненте
  • Конечная цель - передать urlQuery из Navbar.js каким-то образом в Episodes.js компонент, чтобы я мог запросить REST api

Как мне достичь желаемое поведение, пожалуйста, помогите

Приложение. js

import React, { useState } from 'react';
import './App.css'
import Episodes from './components/Episodes/Episodes'
import CustomNavbar from './components/Navbar/Navbar'
import Pagination from './components/Pagination/Pagination'
function App() {

  const [postsPerPage] = useState(20);
  const [currentPage, setCurrentPage] = useState(1);

  const url=`https://rickandmortyapi.com/api/episode?page=${currentPage}`
  let urlQuery = `https://rickandmortyapi.com/api/episode?name=${SEARCH TEXT HERE}`

  const paginate = pageNumber => setCurrentPage(pageNumber);

  return (
    <div>
      <CustomNavbar />
      <Episodes
      urlQuery={urlQuery}
      url={url}
      />
      <Pagination
        postsPerPage={postsPerPage}
        totalPosts={36}
        paginate={paginate}
      />
    </div>
  );
}

export default App;

Navbar. js

import React from 'react';
import Navbar from 'react-bootstrap/Navbar';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import FormControl from 'react-bootstrap/FormControl';

const customNavbar = () => {

  return (
    <Navbar bg="light" expand="lg">
      <Navbar.Brand href="#home">Rick And Morty</Navbar.Brand>
      <Form inline>
        <FormControl type="text" placeholder="Search" />
        <Button>Search</Button>
      </Form>
    </Navbar>
  );
}
export default customNavbar

Edit

По предложению Zohaib эта ошибка выдается

Failed to compile.

./src/components/Navbar/Navbar.js
  Line 14:48:  Unexpected use of 'event'  no-restricted-globals

Search for the keywords to learn more about each error.   

Ответы [ 4 ]

1 голос
/ 19 июня 2020

Существует руководство React по этой конкретной c проблеме: Подъем состояния .

Обычно вы управляете состоянием в родительском элементе. В данном случае App, где вы управляете состоянием текста поиска. Вы передаете функцию компонентам, чтобы изменить это состояние. Компоненты, которые зависят от этого состояния, передают значение через свойства.

Вот пример:

const {useEffect, useState} = React;

function App() {
  const episodesURL = "https://rickandmortyapi.com/api/episode";
  
  const [page, setPage] = useState(1);
  const [pageInfo, setPageInfo] = useState({});
  const [searchText, setSearchText] = useState("");
  const [episodes, setEpisodes] = useState([]);
  
  useEffect(() => {
    const url = new URL(episodesURL);
    url.searchParams.set("page", page);
    if (searchText) url.searchParams.set("name", searchText);
    
    fetch(url)
    .then(response => response.json())
    .then(response => {
      if (response.error) {
        setPageInfo({});
        setEpisodes([]);
      } else {
        setPageInfo(response.info);
        setEpisodes(response.results);
      }
    });
  }, [page, searchText]);

  const search = searchText => {
    setSearchText(searchText);
    setPage(1);
  };
  
  return (
    <div>
      <CustomNavbar search={search} />
      <Episodes episodes={episodes} />
      <Pagination setPage={setPage} info={pageInfo} />
    </div>
  );
}

function CustomNavbar({search}) {
  const [searchText, setSearchText] = useState("");
  
  const handleFormSubmit = event => {
    event.preventDefault();
    search(searchText);
  };
  
  return (
    <form onSubmit={handleFormSubmit}>
      <input
        type="text"
        placeholder="search"
        value={searchText}
        onChange={event => setSearchText(event.target.value)}
      />
      <button type="submit">Search</button>
    </form>
  );
}

function Episodes({episodes}) {  
  return (
    <table>
      <thead>
        <tr>
          <th>episode</th>
          <th>name</th>
          <th>air date</th>
        </tr>
      </thead>
      <tbody>
        {episodes.map(episode => (
          <tr key={episode.id}>
            <td>{episode.episode}</td>
            <td>{episode.name}</td>
            <td>{episode.air_date}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

function Pagination({setPage, info}) {
  return (
    <div>
      {info.prev && <a onClick={() => setPage(page => page - 1)}>previous</a>}
      {info.next && <a onClick={() => setPage(page => page + 1)}>next</a>}
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
th { text-align: left; }
a { cursor: pointer; }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
1 голос
/ 19 июня 2020

Вы имеете в виду что-то вроде this ?

1 голос
/ 19 июня 2020

Приложение. js

import React, { useState, useEffect } from 'react';
import './App.css'
import Episodes from './components/Episodes/Episodes'
import CustomNavbar from './components/Navbar/Navbar'
import Pagination from './components/Pagination/Pagination'
function App() {

  const [postsPerPage] = useState(20);
  const [currentPage, setCurrentPage] = useState(1);
  const [userSearchValue, setUserSearchValue] = useState('');

  const [url, setUrl] = useState(``);
  const [urlQuery, setUrlQuery] = useState(``)

  useEffect(() => {
    setUrl(`https://rickandmortyapi.com/api/episode?page=${currentPage}`)
  }, [currentPage]);

  useEffect(() => {
    setUrlQuery(`https://rickandmortyapi.com/api/episode?name=${userSearchValue}`)
  }, [userSearchValue])

  const paginate = pageNumber => setCurrentPage(pageNumber);

  const handleButtonClick = (searchValue) => {
      setUserSearchValue(searchValue);
  }

  return (
    <div>
      <CustomNavbar
      onButtonClick={handleButtonClick}
      />
      <Episodes
      urlQuery={urlQuery}
      url={url}
      />
      <Pagination
        postsPerPage={postsPerPage}
        totalPosts={36}
        paginate={paginate}
      />
    </div>
  );
}

export default App;

Navbar. js

import React, { useState } from 'react';
import Navbar from 'react-bootstrap/Navbar';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import FormControl from 'react-bootstrap/FormControl';

const customNavbar = ({ onButtonClick }) => {

    const [searchValue, setSearchValue] = useState('');

  return (
    <Navbar bg="light" expand="lg">
      <Navbar.Brand href="#home">Rick And Morty</Navbar.Brand>
      <Form inline>
        <FormControl type="text" placeholder="Search" value={searchValue} onChange={(e) => setSearchValue(e.target.value)} />
        <Button onClick={() => onButtonClick(searchValue)}>Search</Button>
      </Form>
    </Navbar>
  );
}
export default customNavbar

Важная часть здесь - это вы ' повторная передача функции handleButtonClick дочернему компоненту (панели навигации). Таким образом, вы можете вызывать эту родительскую функцию в дочернем компоненте, когда захотите (ie. Когда пользователь нажимает кнопку отправки).

0 голосов
/ 19 июня 2020

Заменить urlQuery на переменную состояния. Затем передайте setUrlQuery в NavBar в качестве опоры, а при нажатии кнопки поиска clickEvent вызовите функцию setUrlQuery.

...