I'm trying to fetch data from an API based on the year parameter with the initial year set to 2020. The components are on the same .jsx page and exported to App.js. When I try to log "search" it returns an empty object.
export default function Rank() {
const [ search, setSearch ] = useState(2020)
console.log(search)
return (
<main>
<div>
<SearchBar onSubmit={setSearch} />
</div>
<div>
<FetchTable />
</div>
</main>
);
}
I've removed some unrelated code in the FetchTable function but basically, it should return a table with data of the selected year.
function FetchTable(search) {
console.log(search)
useEffect(() => {
fetch(`exampleapiurl?year=${search}`)
function SearchBar(props) {
const [ innerSearch, setInnerSearch ] = useState();
return (
<div>
<input
aria-labelledby="search-button"
name="search"
id="search"
type="search"
value={innerSearch}
onChange={(e) => setInnerSearch(e.target.value)}
/>
<button
id="search-button"
type="button"
onClick={() => props.onSubmit(innerSearch)}
>
Search
</button>
</div>
)
}
Any help greatly appreciated.
You need to pass the search parameter to the FetchTable, and get it from the props. See comments in code.
const { useState, useEffect } = React
function Rank() {
const [search, setSearch] = useState(2020)
return (
<main>
<div>
<SearchBar onSubmit={setSearch} />
</div>
<div>
{/* pass search to FetchTable */}
<FetchTable search={search} />
</div>
</main>
)
}
function FetchTable({ search }) { // get search from the props
useEffect(() => {
// fetch(`exampleapiurl?year=${search}`)
console.log(search)
}, [search]) // useEffect should depend on search
return (
<div>{search}</div>
)
}
function SearchBar({ onSubmit }) {
const [innerSearch, setInnerSearch] = useState(''); // set an initial value to the state, so the input would be controlled
return (
<div>
<input
aria-labelledby="search-button"
name="search"
id="search"
type="text"
value={innerSearch}
onChange={(e) => setInnerSearch(e.target.value)}
/>
<button
id="search-button"
type="button"
onClick={() => onSubmit(innerSearch)}
>
Search
</button>
</div>
)
}
ReactDOM.render(
<Rank />,
root
)
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>
Related
I am trying to understand how to share hooks state across components. But it doesn't seem to be sharing. Am I doing something wrong here?
Home.js
export default function Home() {
const [search, setSearch]= useState('');
return (
<div>
<Input search={search} handleChange={setSearch} />
<Products search={search} handleChange={setSearch} />
</div>
)
}
Input.js
export default function Input({search, setSearch}) {
const handleChange = (e) => {
setSearch(e.target.value)
}
return (
<div className='App'>
<input
placeholder='search...'
value={search}
onChange={handleChange}
/>
{search}
</div>
)
}
Live Example:
const { useState } = React;
/*export default*/ function Home() {
const [search, setSearch]= useState('');
return (
<div>
<Input search={search} handleChange={setSearch} />
<Products search={search} handleChange={setSearch} />
</div>
)
}
/*export default*/ function Input({search, setSearch}) {
const handleChange = (e) => {
setSearch(e.target.value)
}
return (
<div className='App'>
<input
placeholder='search...'
value={search}
onChange={handleChange}
/>
{search}
</div>
)
}
const Products = ({search}) => {
return <div>Product: {search}</div>;
};
ReactDOM.createRoot(document.getElementById("root"))
.render(<Home />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.0.0/umd/react-dom.development.js"></script>
You pass handleSearch as prop in your Home component but Input is expecting setSearch, so just change this line in your Home
return (
<div>
<Input search={search} setSearch={setSearch} /> // change here
<Products search={search} handleChange={setSearch} />
</div>
)
How to make todo list in react.I am following some tutorial how to work with react. This code is using input for adding item to list . How can I add item over h3 element instead input element?
This code is working perfect , I am looking for another way . Thank you
Here is full code .
import { useState } from 'react'
import { v4 as uuidV4 } from 'uuid'
const Header = () => {
const [input, setInput] = useState('')
const [todos, setTodos ] = useState([])
const onInput = (e) => {
setInput(e.target.value)
console.log(input)
}
const onFormSubmit = (e) => {
e.preventDefault()
setTodos([...todos, {id: uuidV4(), title:input, completed:false}])
setInput('')
}
return (
<section className='header'>
<h1>ToDo List</h1>
<form onSubmit={onFormSubmit}>
<input
type="text"
placeholder='Add Item'
className='input'
value={input}
required
onChange={onInput} />
<button
className='btn'
type='submit' > Add </button>
</form>
<br /><br />
<ul>
{todos.map((todo) => (
<li className='todo-list'> // here is output
// <h3> { ? } </h3> it should go todo.title
// can you show me how, pls ?
<input
type="text"
value={todo.title}
className='list'
onChange={(e)=>e.preventDefault()} />
</li>
))}
</ul>
</section>
)
};
export default Header;
Get the title of the todo from the todo object passed to .map() function.
<h3>{todo.title}</h3>
// Get a hook function
const {useState} = React;
const Header = () => {
const [input, setInput] = useState("");
const [todos, setTodos] = useState([]);
const onInput = (e) => {
setInput(e.target.value);
//console.log(input);
};
const onFormSubmit = (e) => {
e.preventDefault();
setTodos([...todos, { id: Math.random(), title: input, completed: false }]);
setInput("");
};
return (
<section className="header">
<h1>ToDo List</h1>
<form onSubmit={onFormSubmit}>
<input
type="text"
placeholder="Add Item"
className="input"
value={input}
required
onChange={onInput}
/>
<button className="btn" type="submit">
{" "}
Add{" "}
</button>
</form>
<br />
<br />
<ul>
{todos.map((todo) => (
<li className="todo-list">
<h3> {todo.title} </h3>
<input
type="text"
value={todo.title}
className="list"
onChange={(e) => e.preventDefault()}
/>
</li>
))}
</ul>
</section>
);
};
// Render it
ReactDOM.render(
<Header />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
hello I'm currently learning about React, and I'm confused about how to pass data or state to another component
i have Search Component like this
function Search(props) {
const [ query, setQuery ] = useState("")
const [ movie, setMovie ] = useState({})
function searchHandler() {
axios.get(`${api.url}SearchMovie/${api.key}/${query}`)
.then(res => {
setMovie(res.data.results)
}).catch(err => {
console.log(err)
})
}
return (
<div className="search-input">
<div class="input-group input-custom mb-3">
<input
type="text"
class="form-control"
placeholder="Search Movie"
onChange={e => setQuery(e.target.value)}
value={query}
/>
<button
class="btn btn-outline-primary"
onClick={searchHandler}
>
Search
</button>
</div>
</div>
);
}
export default Search;
and also MainPage Component like this
function MainPage() {
return (
<div>
<Navbar />
<div className="container">
<Search />
<hr />
<div className="content">
<div className="row">
<div className="col-4">
<Card
image="https://dbkpop.com/wp-content/uploads/2020/06/weeekly_we_are_teaser_2_monday.jpg"
title="Monday"
description="Monday Weeekly Member"
/>
</div>
<div className="col-4">
<Card
image="https://dbkpop.com/wp-content/uploads/2020/06/weeekly_we_are_teaser_2_monday.jpg"
title="Monday"
description="Monday Weeekly Member"
/>
</div>
<div className="col-4">
<Card
image="https://dbkpop.com/wp-content/uploads/2020/06/weeekly_we_are_teaser_2_monday.jpg"
title="Monday"
description="Monday Weeekly Member"
/>
</div>
</div>
</div>
</div>
</div>
);
}
export default MainPage;
the problem is, how to pass State (movie) from Search Component to MainPage Component. so that I can render the data to MainPage Component
Data in React flows down, so you need to lift the state up.
Hence, the movie state should be in scope of MainPage:
function MainPage() {
const [ movie, setMovie ] = useState({})
// Set query results with setMovie
return <Search setMovie={setMovie} ... />
}
function Search(props) {
function searchHandler() {
axios.get(`${api.url}SearchMovie/${api.key}/${query}`)
.then(res => {
props.setMovie(res.data.results)
}).catch(err => {
console.log(err)
})
}
return (...);
}
export default Search;
On click on a button how can we create a dynamic form url with below fields using react hooks and url globally valid only for 48 hrs.
https://localhost/aB123GHedFGH138HGxYz/recommendform
import React, { useState, useEffect, useRef } from "react";
import "./styles.css";
export default function App() {
// nominee text field
// description
// nominatedby
// save button
// cancel button
const [createForm, setCreateForm] = useState([
{ nominee: "", description: "", nominatedby: "" }
]);
const inputForm = (choiceForm) => {
alert("Hello");
};
return (
<div className="App">
<h1>Form</h1>
<form>
{createForm.map((field, index) => {
<div key={index}>
<input name="nominee" type="text" />
</div>;
})}
<input value="Create Form" type="button" onClick={inputForm} />
</form>
</div>
);
}
https://codesandbox.io/s/wonderful-wilson-hmts5?file=/src/App.js:0-311
Here is an example of creating a form as you asked.
Adding 48h limit globally (meaning it should persist for all users) requires a server, then you will just need to fetch/update the status. See API and AJAX calls in docs.
const formFields = [
["nominee", "Example"],
["description", "Desc"],
["nominatedby", ""]
];
export default function App() {
const [isFormCreated, setIsFormCreated] = useState(false);
const onClickEnableForm = () => setIsFormCreated(true);
return (
<div className="App">
<h1>Form</h1>
{isFormCreated && (
<form>
{formFields.map(([name, value]) => {
return (
<div key={name}>
<input defaultValue={value} name={name} type="text" />
</div>
);
})}
<input type="submit" />
</form>
)}
{!isFormCreated && (
<input value="Create Form" type="button" onClick={onClickEnableForm} />
)}
</div>
);
}
I have a react component named <Filters /> which renders a component <PriceFilter />. The <PriceFilter /> component renders a <Filter /> component and some other JSX.
<Filters /> component:
const Filters = ({ price, setPrice }) => {
return (
<div>
<PriceFilter price={price} setPrice={setPrice} />
</div>
);
};
<PriceFilter /> component:
const PriceFilter = ({price, setPrice}) => {
const [show, setShow] = useState(false);
const toggleShow = () => setShow(!show);
return (
<div>
<Filter show={show} toggleShow={toggleShow}>
Price
</Filter>
{show && (
<FilterContainer>
<div>
<div onClick={() => setPrice('$')}>
<span>Inexpensive</span>
</div>
<div onClick={() => setPrice('$$')}>
<span>$$</span>
</div>
<div onClick={() => setPrice('$$$')}>
<span>$$$</span>
</div>
<div onClick={() => setPrice('$$$$')}>
<span>$$$$</span>
</div>
</div>
</FilterContainer>
)}
</div>
);
};
<Filter /> component:
const Filter = ({children, show, toggleShow}) => {
return (
<div>
<span>{children}</span>
{show ? <KeyboardArrowUpIcon onClick={toggleShow} /> : <KeyboardArrowDownIcon onClick={toggleShow} />}
</div>
);
};
Clicking on any of the options (Inexpensive/$$/$$$/$$$$) in the <PriceFilter /> component not only sets the state to the value passed ('$'/'$$'/'$$$'/'$$$$'), but it is also triggering the toggleShow function for some reason. Can someone please provide a solution to this so that the toggleShow function isn't called when clicking on the option.
The code works with minimal setup. See what is going wrong in higher level component Test where Filters is being rendered.
export const Test = () => {
const [price, setPrice] = useState('inexpensive')
return(
<Filters price={price} setPrice={setPrice} />
)
}
const Filters = ({ price, setPrice }) => {
return (
<div>
<PriceFilter price={price} setPrice={setPrice} />
</div>
);
};
const PriceFilter = ({price, setPrice}) => {
const [show, setShow] = useState(false);
const toggleShow = () => {
setShow(!show);
}
return (
<div>
<Filter show={show} toggleShow={toggleShow}>
{price}
</Filter>
{show && (
<div>
<div>
<div onClick={() => setPrice('$')}>
<span>Inexpensive</span>
</div>
<div onClick={() => setPrice('$$')}>
<span>$$</span>
</div>
<div onClick={() => setPrice('$$$')}>
<span>$$$</span>
</div>
<div onClick={() => setPrice('$$$$')}>
<span>$$$$</span>
</div>
</div>
</div>
)}
</div>
);
};
const Filter = ({children, show, toggleShow}) => {
return (
<div>
<span>{children}</span>
{show ? <div onClick={toggleShow}>up</div> : <div onClick={toggleShow}>down</div>}
</div>
);
};
It's working!! I didn't get why but there was a problem in the parent component. I had created a local component in the parent and rendered it there. I just extracted that local component in an independent component and it works now.