Reputation: 485
What i want to do :
Search
in Navbar.js
i want to assign the search text in the variable urlQuery
so i can pass it as props in Episodes.js
componentNavbar.js
somehow to Episodes.js
component so i can query the REST apiHow do i achieve the desired behaviour pls help
App.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
On Zohaib's suggestion this error is thrown
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.
Upvotes: 1
Views: 1541
Reputation: 21130
There is a React guide about this specific problem: Lifting State Up.
Normally what you do is you manage the state in the parent. In this case App
where you manage the search text state. You pass down a function to components to change this state. The components that depend upon this state are passed the value through the properties.
Here is an example:
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>
Upvotes: 1
Reputation: 1082
App.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
The important part here is you're passing down the handleButtonClick
function to the child component (Navbar). This way you can call that parent function in the child component whenever you want (ie. when the user clicks the submit button).
Upvotes: 1
Reputation: 310
Change urlQuery to state variable. Then, pass setUrlQuery to NavBar as a prop and on search button clickEvent call setUrlQuery function.
Upvotes: 0