I am working on a simple ShoppinList. I have two components, Form.js and List.j. How can I display in List.js the items that are stored in list array in Form.js ? I don't want useState to be written in App.js, but would keep the logic separate in its own components.
App.js:
//Imporing Components
import Form from "./Components/Form";
import List from "./Components/List";
function App() {
return (
<div className="App">
<header>
<h1>Shopping List</h1>
</header>
<Form/>
<List/>
</div>
)
}
Form.js:
/*Create a Component*/
const Form = () => {
const [inputText,setInputText] = useState("")
const [list,setList] = useState([])
const submitBtn = (e) =>{
e.preventDefault() /*kein refresh tätigen*/
setList([
...list,{inputText}
])
}
/*Funktion*/
/*const inputTextHandler = (e) => {
setInputText(e.target.value)
}*/
return (
<form>
<input
value={inputText}
type="text"
onChange={
(e) => setInputText(e.target.value)
}
/>
<button type="submit" onClick={submitBtn}>
<i>Add</i>
</button>
</form>
)
}
export default Form
List.js:
import React, {useState} from "react";
const List = () =>{
return(
<div>
<ul>{[List]}</ul>
</div>
)
}
export default List
In React state goes top to bottom. A nested component can update the state of a parent if a function defined in the parent has been passed to it as props. Which means, what you wanna do is not possible as you wanna pass state between sibling components (List.js and Form.js).
For this to work, you should have the state for the list in a parent component, App.js for example, this way:
import Form from "./Components/Form";
import List from "./Components/List";
import {useState} from "react";
function App() {
const [list, setList] = useState([])
return (
<div className="App">
<header>
<h1>Shopping List</h1>
</header>
<Form list = {list} setList = {setList}/>
<List list = {list} />
</div>
)
}
import React, {useState} from "react";
const List = ({list}) =>{
return(
<div>
<ul>{list.map(item => <li>"test"</li>)}</ul>
</div>
)
}
export default List
const Form = ({list, setList}) => {
const [inputText,setInputText] = useState("")
const submitBtn = (e) =>{
e.preventDefault()
setList([
...list,{inputText}
])
}
return (
<form>
<input
value={inputText}
type="text"
onChange={
(e) => setInputText(e.target.value)
}
/>
<button type="submit" onClick={submitBtn}>
<i>Add</i>
</button>
</form>
)
}
export default Form
You can't pass props to sibling component without passing it to parent component. Alternative way is to use state managers such as Redux, Effector or at least React Context.
The way React works:
import Form from "./Components/Form";
import List from "./Components/List";
function App() {
const [list, setList] = useState([]);
const formSubmitHandler = (passedData) => {
setList(passedData);
}
return (
<div className="App">
<Form onSubmitting={formSubmitHandler}/>
<List list={list}/>
</div>
)
}
You can't really do what you're asking as React only allows child components to accept state from parent components, it is a top-down process. I would recommend using a React "Context"; A context will allow you to have one component that can share state throughout the entire component tree without having to pass props down through child components. It's basically a store for the whole react app, that can be pulled wherever and whenever needed.