I would like to display in a paragraph tag the results of a function after an input. This is what I have tried:
import React, { useState } from "react";
const Measurement = () => {
const [brightness, setBrightness] = useState(0);
const [darkness, setDarkness] = useState(0);
const checkLumens = () => {
if (brightness > 120) {
return "High";
}
if (darkness < 80) {
return "Low";
}
else {
return "Not Set";
}
};
return (
<div>
<input
type="number"
onChange={(event) => setBrightness(event.target.value)}
/>
<button>Show</button>
<p>{checkLumens()}</p> //Hide by default and show {checkLumens()} after button click
</div>
);
};
export default Measurement;
Thanks for the help!
Create a state to show and hide the lumens value using useState, and change the value on button click
const Measurement = () => {
const [brightness, setBrightness] = useState(0);
const [darkness, setDarkness] = useState(0);
const [showLumens, setShowLumnes] = useState(false);
const checkLumens = () => {
if (brightness > 120) {
return "High";
}
if (darkness < 80) {
return "Low";
}
else {
return "Not Set";
}
};
return (
<div>
<input
type="number"
onChange={(event) => setBrightness(event.target.value)}
/>
<button onClick={()=>setShowLumnes(true)}>Show</button>
{showLumens && <p>{checkLumens()}</p>}
</div>
);
};
export default Measurement;
Just add a new state variable:
import React, { useState } from "react";
const Measurement = () => {
const [brightness, setBrightness] = useState(0);
const [darkness, setDarkness] = useState(0);
const [showLumens, setShowLumens] = useState(false);
const checkLumens = () => {
if (brightness > 120) {
return "High";
}
if (darkness < 80) {
return "Low";
}
else {
return "Not Set";
}
};
return (
<div>
<input
type="number"
onChange={(event) => setBrightness(event.target.value)}
/>
<button onClick={() => setShowLumens(true)}>Show</button>
<p>{showLumens ? checkLumens() : null}</p> //Hide by default and show {checkLumens()} after button click
</div>
);
};
export default Measurement;
import React, { useState, useEffect } from "react";
const Measurement = () => {
const [brightness, setBrightness] = useState(0);
const [darkness, setDarkness] = useState(0);
const [lumens, setLumens] = useState('Not Set')
const [show, setShow] = useState(false)
useEffect(() => {
if (brightness > 120) {
setLumens("High");
}
if (darkness < 80) {
setLumens("Low");
}
else {
setLumens("Not Set");
}
}, [darkness, brightness])
return (
<div>
<input
type="number"
onChange={(event) => setBrightness(event.target.value)}
/>
<button onClick={() => setShow(true)}>Show</button>
<p>{show && lumens}</p> //Hide by default and show {checkLumens()} after button click
</div>
);
};
export default Measurement;
Related
I currently have a <textarea/> field that when you press enter it submits and makes a new item on the array. When you press shift + enter it creates a new line in the <textarea/> input field.
However, when you actually press shift and enter to make a new break and submit it; it does not recognize the break in the line. I have attached images below.
As you can see above, its like the array does not recognize there is a break in the input.
Todobox.jsx:
import React, { createContext } from 'react';
import Item from './Item';
import { useState, useContext } from 'react';
import '../App.css';
import trash from '../trash_can.png'
import { ElementContext } from '../ElementContext';
export const ItemContext = createContext();
export const ItemContextProvider = ({ children }) => {
const [items, setItems] = useState([]);
const [itemId, setItemId] = useState(1);
const [itemData, setItemData] = useState();
const [refDict, setRefDict] = useState({});
const newItemId = (items) =>{
setItemId(itemId + 1);
console.log(itemId)
}
const newItem = (itemChange, boxid) => {
newItemId();
if (!refDict[itemId]) {
setItems(prev => [...prev, { itemboxid: boxid, itemdata: itemChange, itemid: itemId }]);
setRefDict((prev) => ({...prev, [itemId]: true}));
}
console.log(items);
};
const value = {
items,
setItems,
newItem,
itemId
};
return(
<ItemContext.Provider value={value}>
{children}
</ItemContext.Provider>
)
};
export default function Todobox({ boxtitle, boxid }){
const { elements, setElements, newTitle } = useContext(ElementContext);
const { items, setItems, newItem } = useContext(ItemContext);
const [boxheader, setBoxHeader] = useState('');
const [itemChange, setItemChange] = useState('');
const handleChange = (e) => {
setBoxHeader(e.target.value);
}
const handleKeydown = (e) => {
if(e.keyCode == 13 && e.shiftKey == false){
setElements(elements.map(element => {
if (element.boxid === boxid) {
setBoxHeader(e.target.value)
return { ...element, boxtitle: boxheader };
} else {
return element;
}
}))
e.preventDefault();
alert('Title has been set to: ' + boxheader);
}
}
const handleDelete = (e) => {
setElements(elements.filter(element => element.boxid !== boxid))
}
const handleItemChange = (e) =>{
setItemChange(e.target.value);
}
const handleNewItem = (e) =>{
if(e.keyCode == 13 && e.shiftKey == false){
newItem(itemChange, boxid)
e.preventDefault();
e.target.value = '';
}
}
return(
<>
<div className='element-box'>
<img src={trash} className='element-box-trash' onClick={handleDelete}></img>
<textarea className='element-title-input' placeholder='Add title...' onChange={handleChange} onKeyDown={handleKeydown} value={boxheader}></textarea>
{items.map(item => {
if(item.itemboxid === boxid){
return <Item key={item.itemid} itemid={item.itemid} itemdata={item.itemdata}/>;
} else if(item.itemboxid !== boxid){
return null;
}
})}
<textarea
className='element-input'
type='text'
placeholder={`Add item... ${boxid}`}
onChange={handleItemChange}
onKeyDown={handleNewItem}
onClick={() => {console.log(boxid)}}
/>
</div>
</>
)
}
Item.jsx:
import React, { useContext } from 'react';
import '../App.css';
import { ElementContext } from '../ElementContext';
import { ItemContext } from './Todobox';
export default function Item({ itemid, itemdata }){
const { setHideModal, modals, setModals } = useContext(ElementContext);
const handleNewModal = () => {
setHideModal(false)
setModals(prev => [...prev, { modalItemId: itemid, modalId: '1', modalData: itemdata }]);
console.log(modals);
};
return(
<div className='item-container' onClick={handleNewModal}>
<a className='item-text'>{itemdata}</a>
</div>
)
}
Item-input css:
.item-text {
padding: 2px;
opacity: 1;
word-wrap: break-word;
}
Any help would be appreciated, thank you in advanced! :)
#caTS answered my question in a comment.
I had to add white-space: pre-wrap to my CSS.
So, i (Total react beginner) have this React component.
import './cryptography.css';
import {useRef} from 'react';
import useInterval from 'react-useinterval';
import { useState } from 'react';
const DisplayTimer = () => {
const [time, setTime] = useState(0);
useInterval(() => {
setTime(time + 1);
}
, 1000);
const hours = Math.floor(time / 3600);
const minutes = Math.floor((time % 3600) / 60);
const seconds = time % 60;
return (
<div className="timer">
<h3>Timer</h3>
<p>{hours.toString().padStart(2, '0')}:{minutes.toString().padStart(2, '0')}:{seconds.toString().padStart(2, '0')}</p>
</div>
)
}
const CryptoOne = () => {
const inputRef = useRef();
function verifyAnswer() {
if (inputRef.current.value === "c6e24b99a8054ab24dd0323530b80819") {
alert("Correct!");
}
else {
alert("Wrong!");
}
}
return (
<div className="crypto-one">
<h3>Level One</h3>
<p>Convert this plaintext into an MD5 hash - "RollingStonesGatherNoMoss"</p>
<input ref={inputRef} type="text" id="one-answer" name="one-answer" />
<button onClick={verifyAnswer}>Submit</button>
</div>
)
}
const CryptoTwo = () => {
const inputRef = useRef();
function verifyAnswer() {
if (inputRef.current.value === "IaMaHackerManHaHa") {
alert("Correct!");
}
else {
alert("Wrong!");
}
}
return (
<div className="crypto-two">
<h3>Level Two</h3>
<p>Decode Caesar cipher into plaintext - "FxJxExzhboJxkExEx"</p>
<input ref={inputRef} type="text" id="two-answer" name="two-answer" />
<button onClick={verifyAnswer}>Submit</button>
</div>
)
}
const CryptoThree = () => {
const inputRef = useRef();
function verifyAnswer() {
let input = inputRef.current.value;
let answer = "SHA256".toLowerCase();
if (input === answer) {
alert("Correct!, completed the exercise");
}
else {
alert("Wrong!");
}
}
return (
<div className="crypto-three">
<h3>Level Three</h3>
<p>Identify the type of the hash (Type only the hash type, with no spaces) - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"</p>
<input ref={inputRef} type="text" id="three-answer" name="three-answer" />
<button onClick={verifyAnswer}>Submit</button>
</div>
)
}
const Cryptography = () => {
const [active, setActive] = useState("crypto-one");
return (
<div className="cryptography">
<h1>Cryptography</h1>
<DisplayTimer />
<div className="crypto-container">
<CryptoOne />
</div>
</div>
)
}
export { Cryptography };
Here, i have this cryptography function that will display a question and if it is correct, that question will be replaced with another.
I have 3 seperate functions CryptoOne, CryptoTwo and CryptoThree which will be displayed in function Cryptography. So that means if the answer for the question for CryptoOne is correct, then it will be replaced with CryptoTwo and so on. So my questions is HOW DO I DO IT?
Thanks in advance.
ANSWER TO YOUR LAST COMMENT TO HANDLE TIMER
Instead of using react-useinterval you could create a useTimer() hook of your own
import { useEffect, useRef, useState } from "react";
const useTimer = () => {
const [time, setTime] = useState(0);
const hours = Math.floor(time / 3600);
const minutes = Math.floor((time % 3600) / 60);
const seconds = time % 60;
let interval = useRef();
useEffect(() => {
interval.current = setInterval(() => {
setTime(prevTime => prevTime + 1);
}, 1000);
return () => {
clearInterval(interval.current);
};
}, [setTime]);
const stopTimer = () => {
clearInterval(interval.current);
};
return { hours, minutes, seconds, stopTimer };
};
export default useTimer;
You can maintain a activeIndex state in Cryptography component. And have a changeSlide method which increments activeSlideIndex by 1 everytime the answer is correct. As shown below
TIMER RELATED COMMENT
Use that hook in Cryptography component. Pass hours, minutes & seconds as props in DisplayTimer component. And pass stopTimer function to CryptoThree component & use it when final answer is complete
const Cryptography = () => {
const [active, setActive] = useState("crypto-one");
const [activeIndex, setActiveIndex] = useState(1);
const { hours, minutes, seconds, stopTimer } = useTimer();
const incrementIndex = () => {
setActiveIndex(prevIndex => prevIndex + 1);
};
return (
<div className="cryptography">
<h1>Cryptography</h1>
<DisplayTimer hours={hours} minutes={minutes} seconds={seconds} />
<div className="crypto-container">
{activeSlideIndex === 1 && <CryptoOne changeIndex={incrementIndex} />}
{activeSlideIndex === 2 && <CryptoTwo changeIndex={incrementIndex} />}
{activeSlideIndex === 3 && <CryptoThree stopTimer={stopTimer} />}
</div>
</div>
);
};
const DisplayTimer = ({ hours, minutes, seconds }) => {
return (
<div className="timer">
<h3>Timer</h3>
<p>
{hours.toString().padStart(2, "0")}:
{minutes.toString().padStart(2, "0")}:
{seconds.toString().padStart(2, "0")}
</p>
</div>
);
};
You can pass this changeSlide() method as a prop in every component.
And call it whenever the answer is correct
const CryptoOne = ({ changeIndex }) => {
const inputRef = useRef();
function verifyAnswer() {
if (inputRef.current.value === "c6e24b99a8054ab24dd0323530b80819") {
alert("Correct!");
changeIndex();
} else {
alert("Wrong!");
}
}
return (
<div className="crypto-one">
<h3>Level One</h3>
<p>
Convert this plaintext into an MD5 hash - "RollingStonesGatherNoMoss"
</p>
<input ref={inputRef} type="text" id="one-answer" name="one-answer" />
<button onClick={verifyAnswer}>Submit</button>
</div>
);
};
const CryptoTwo = ({ changeIndex }) => {
const inputRef = useRef();
function verifyAnswer() {
if (inputRef.current.value === "IaMaHackerManHaHa") {
alert("Correct!");
changeIndex();
} else {
alert("Wrong!");
}
}
return (
<div className="crypto-two">
<h3>Level Two</h3>
<p>Decode Caesar cipher into plaintext - "FxJxExzhboJxkExEx"</p>
<input ref={inputRef} type="text" id="two-answer" name="two-answer" />
<button onClick={verifyAnswer}>Submit</button>
</div>
);
};
const CryptoThree = ({stopTimer) => {
const inputRef = useRef();
function verifyAnswer() {
let input = inputRef.current.value;
let answer = "SHA256".toLowerCase();
if (input === answer) {
alert("Correct!, completed the exercise");
stopTimer(); // Use stopTimer here when exercise is complete
} else {
alert("Wrong!");
}
}
return (
<div className="crypto-three">
<h3>Level Three</h3>
<p>
Identify the type of the hash (Type only the hash type, with no spaces)
- "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
</p>
<input ref={inputRef} type="text" id="three-answer" name="three-answer" />
<button onClick={verifyAnswer}>Submit</button>
</div>
);
};
I'm working on a React Notes Application and my App.js contains all the necessary functions props which are passed down to several components.
As a result I'm doing prop drilling a lot where I'm passing down around 10-20 props/functions in the components where it isn't needed.
I tried using useContext Hook but I guess it doesn't work with callback functions in the value parameter.
App.js
const App = () => {
const [ notes, setNotes ] = useState([]);
const [ category, setCategory ] = useState(['Notes']);
const [ searchText, setSearchText ] = useState('');
const [ alert, setAlert ] = useState({
show:false,
msg:'',
type:''
});
const [isEditing, setIsEditing] = useState(false);
const [editId, setEditId] = useState(null);
useEffect(()=>{
keepTheme();
})
// retreive saved notes
useEffect(()=>{
const savedNotes = JSON.parse(localStorage.getItem('react-notes-data'));
if (savedNotes) {
setNotes(savedNotes)
}
}, []);
// save notes to local storage
useEffect(() => {
localStorage.setItem('react-notes-data', JSON.stringify(notes))
setNotesCopy([...notes]);
}, [notes]);
// save button will add new note
const addNote = (text) => {
const date = new Date();
const newNote = {
id: nanoid(),
text: text,
date: date.toLocaleDateString(),
category: category,
}
const newNotes = [...notes, newNote]
setNotes(newNotes);
}
const deleteNote = (id) => {
showAlert(true, 'Note deleted', 'warning');
const newNotes = notes.filter(note => note.id !== id);
setNotes(newNotes);
}
// hardcoded values for categories
const allCategories = ['Notes', 'Misc', 'Todo', 'Lecture Notes', 'Recipe'];
// copy notes for filtering through
const [notesCopy, setNotesCopy] = useState([...notes]);
const handleSidebar = (category) => {
setNotesCopy(category==='Notes'?[...notes]:
notes.filter(note=>note.category===category));
}
// function to call alert
const showAlert = (show=false, msg='', type='') => {
setAlert({show, msg, type});
}
return (
<div>
<div className="container">
<Sidebar
allCategories={allCategories}
handleSidebar={handleSidebar}
notesCopy={notesCopy}
key={notes.id}
/>
<Header notes={notes} alert={alert} removeAlert={showAlert} />
<Search handleSearchNote={setSearchText} />
<NotesList
notesCopy={notesCopy.filter(note=>
note.text.toLowerCase().includes(searchText) ||
note.category.toString().toLowerCase().includes(searchText)
)}
handleAddNote={addNote}
deleteNote={deleteNote}
category={category}
setCategory={setCategory}
allCategories={allCategories}
showAlert={showAlert}
notes={notes}
setNotes={setNotes}
editId={editId}
setEditId={setEditId}
isEditing={isEditing}
setIsEditing={setIsEditing}
/>
</div>
</div>
)
}
NotesList.js
const NotesList = (
{ notesCopy, handleAddNote, deleteNote, category, setCategory, showHideClassName, allCategories, showAlert, isEditing, setIsEditing, notes, setNotes, editId, setEditId }
) => {
const [ noteText, setNoteText ] = useState('');
const textareaRef = useRef();
// function to set edit notes
const editItem = (id) => {
const specificItem = notes.find(note=>note.id === id);
setNoteText(specificItem.text);
setIsEditing(true);
setEditId(id);
textareaRef.current.focus();
}
return (
<div key={allCategories} className="notes-list">
{notesCopy.map(note => {
return (
<Note
key={note.id}
{...note}
deleteNote={deleteNote}
category={note.category}
isEditing={isEditing}
editId={editId}
editItem={editItem}
/>)
})}
<AddNote
handleAddNote={handleAddNote}
category={category}
setCategory={setCategory}
showHideClassName={showHideClassName}
allCategories={allCategories}
showAlert={showAlert}
isEditing={isEditing}
setIsEditing={setIsEditing}
notes={notes}
setNotes={setNotes}
editId={editId}
setEditId={setEditId}
noteText={noteText}
setNoteText={setNoteText}
textareaRef={textareaRef}
/>
</div>
)
}
AddNote.js
const AddNote = ({ notes, setNotes, handleAddNote, category, setCategory, showHideClassName, allCategories, showAlert, isEditing, setIsEditing, editId, setEditId, noteText, setNoteText, textareaRef }) => {
const [ show, setShow ] = useState(false);
const [ modalText, setModalText ] = useState('');
const charCount = 200;
const handleChange = (event) => {
if (charCount - event.target.value.length >= 0) {
setNoteText(event.target.value);
}
}
const handleSaveClick = () => {
if (noteText.trim().length === 0) {
setModalText('Text cannot be blank!');
setShow(true);
}
if (category === '') {
setModalText('Please select a label');
setShow(true);
}
if (noteText.trim().length > 0 && category!=='') {
showAlert(true, 'Note added', 'success');
handleAddNote(noteText);
setNoteText('');
setShow(false);
}
if (noteText.trim().length > 0 && category!=='' && isEditing) {
setNotes(notes.map(note=>{
if (note.id === editId) {
return ({...note, text:noteText, category:category})
}
return note
}));
setEditId(null);
setIsEditing(false);
showAlert(true, 'Note Changed', 'success');
}
}
const handleCategory = ( event ) => {
let { value } = event.target;
setCategory(value);
}
showHideClassName = show ? "modal display-block" : "modal display-none";
return (
<div className="note new">
<textarea
cols="10"
rows="8"
className='placeholder-dark'
placeholder="Type to add a note.."
onChange={handleChange}
value={noteText}
autoFocus
ref={textareaRef}
>
</textarea>
<div className="note-footer">
<small
className='remaining'
style={{color:(charCount - noteText.length == 0) && '#c60000'}}>
{charCount - noteText.length} remaining</small>
<div className='select'>
<select
name={category}
className="select"
onChange={(e)=>handleCategory(e)}
required
title='Select a label for your note'
defaultValue="Notes"
>
<option value="Notes" disabled selected>Categories</option>
{allCategories.map(item => {
return <option key={item} value={item}>{item}</option>
})}
</select>
</div>
<button className='save' onClick={handleSaveClick} title='Save note'>
<h4>{isEditing ? 'Edit':'Save'}</h4>
</button>
</div>
{/* Modal */}
<main>
<div className={showHideClassName}>
<section className="modal-main">
<p className='modal-text'>{modalText}</p>
<button type="button" className='modal-close-btn'
onClick={()=>setShow(false)}><p>Close</p>
</button>
</section>
</div>
</main>
</div>
)
}
I want the functions passed from App.js to NotesList.js to be in AddNote.js without them being passed in NotesList.js basically minimizing the props destructuring in NotesList.js
Context API does work with function. What you need to do is pass your function to Provider inside value :
<MyContext.Provider value={{notes: notesData, handler: myFunction}} >
For example:
// notes-context.js
import React, { useContext, createContext } from 'react';
const Context = createContext({});
export const NotesProvider = ({children}) => {
const [notes, setNote] = useState([]);
const addNote = setNote(...); // your logic
const removeNote = setNote(...); // your logic
return (
<Context.Provider value={{notes, addNote, removeNote}}>
{children}
</Context.Provider>
)
}
export const useNotes = () => useContext(Context);
Add Provider to your App.js like so:
// App.js
import NoteProvider from './notes-context';
export default App = () => {
return (
<NoteProvider>
<div>... Your App</div>
</NoteProvider>
)
}
Then call UseNote in your NoteList.js to use the function:
// NoteList.js
import {useNotes} from './note-context.js';
export const NoteList = () => {
const {notes, addNotes, removeNotes} = useNotes();
// do your stuff. You can now use functions addNotes and removeNotes without passing them down the props
}
Hello I need to setup a progress bar. So when I press on the button progress bar shows, the button and the content inside of it dispears proggress bar starts to go 0 100 and as well shows some text above, and
when it reaches the 100% progress bar disppears and text above, but after that new text shows. Thanks in Advance
import React,{useEffect, useState} from 'react'
import LinearProgress from '#material-ui/core/LinearProgress'
const useStyles = makeStyles({
root: {
width: '100%',
},
});
const Content =(props)=> {
const classes = useStyles();
const[hideContent, setHideContent]= React.useState(false)
const [progress, setProgress] = React.useState(10);
function handleClick12 ()
{setHideEset(true) }
useEffect(() => {
const timer = setInterval(() => {
setProgress((prevProgress) => (prevProgress >= 100 ? 10 : prevProgress + 10));
}, 800);
return () => {
clearInterval(timer);
};
}, []);
return (
{!hideContent &&
<div className='esetNod__info'>
<h3>Hello</h3>
<Button onClick={handleClick12} className='fix__button'variant='outlined'></Button>
<div >
<LinearProgress value={progress} />
</div>
</div>
}
</div>
)
}
export default Content;
I tried to write something for you:
import React, { useState } from "react";
import LinearProgress from "#material-ui/core/LinearProgress";
const Content = () => {
const [isLoading, setIsLoading] = useState(false);
const [hasLoaded, setHasLoaded] = useState(false);
const [progress, setProgress] = useState(0);
const handleClick = () => {
setIsLoading(true);
const interval = setInterval(() => {
setProgress((prevProgress) => {
const next = prevProgress + 10;
if (next === 100) {
clearInterval(interval);
setIsLoading(false);
setHasLoaded(true);
}
return next;
});
}, 800);
};
if (!isLoading && !hasLoaded) {
return (
<div className="esetNod__info">
<h3>Pre load content</h3>
<button onClick={handleClick} className="fix__button">
Load Content
</button>
</div>
);
} else if (isLoading && !hasLoaded) {
return (
<diV>
<h3>Loading content</h3>
<LinearProgress value={progress} />
</diV>
);
} else {
return (
<div>
<h3>Post load content</h3>
</div>
);
}
};
export default Content;
I have a problem that my React app saving 2 same properties on one query.
After I enter the data in two input field and click Set button I receive double of same data.
CODE HERE
import React, { useState } from "react";
export default function App() {
const [queries, setQueries] = useState([]);
const [symbol, setSymbol] = useState("");
const [price, setPrice] = useState("");
const onChangeSymbol = e => {
setSymbol(e.target.value);
};
const onChangePrice = e => {
setPrice(e.target.value);
};
const onClick = () => {
if (symbol !== "" && price !== "") {
setQueries((queries) => {
queries.push(`${symbol}${price}`);
return queries;
});
setSymbol("");
setPrice("");
}
}
return (
<div className="App">
<h6>Price Alert History</h6>
<ul>
{queries.map(query => <li>{query}</li>)}
</ul>
<input
type="text"
placeholder="Symbol"
value={symbol}
onChange={onChangeSymbol}
/>
<input
type="number"
placeholder="Price"
value={price}
onChange={onChangePrice}
/>
<button type="submit" onClick={onClick}>Set</button>
</div>
);
}
GOAL: I just want to receive one property instead of double of it.
You need just to fix your function and it will work properly
const onClick = () => {
if (symbol !== "" && price !== "") {
setQueries((queries) => {
return [ ...queries, `${symbol}${price}`] // fix here
});
setSymbol("");
setPrice("");
}
}
import React, { useState } from "react";
export default function App() {
const [queries, setQueries] = useState([]);
const [symbol, setSymbol] = useState("");
const [price, setPrice] = useState("");
const onChangeSymbol = e => {
setSymbol(e.target.value);
};
const onChangePrice = e => {
setPrice(e.target.value);
};
const onClick = () => {
if (symbol !== "" && price !== "") {
setQueries((queries) => {
return [ ...queries, `${symbol}${price}`]
});
setSymbol("");
setPrice("");
}
}
return (
<div className="App">
<h6>Price Alert History</h6>
<ul>
{queries.map(query => <li>{query}</li>)}
</ul>
<input
type="text"
placeholder="Symbol"
value={symbol}
onChange={onChangeSymbol}
/>
<input
type="number"
placeholder="Price"
value={price}
onChange={onChangePrice}
/>
<button type="submit" onClick={onClick}>Set</button>
</div>
);
}
I would have refactored it so that the price and symbol would be an object with keys
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [queries, setQueries] = useState([]);
const [symbol, setSymbol] = useState("");
const [price, setPrice] = useState("");
const onClick = () => {
if (symbol !== "" && price !== "") {
const product = {
symbol: symbol,
price: price
};
setQueries([...queries, product]);
setSymbol("");
setPrice("");
}
};
return (
<div className="App">
<h6>Price Alert History</h6>
<ul>
{queries.map(query => (
<li>
{query.symbol} {query.price}
</li>
))}
</ul>
<input
type="text"
placeholder="Symbol"
value={symbol}
onChange={e => setSymbol(e.target.value)}
/>
<input
type="number"
placeholder="Price"
value={price}
onChange={e => setPrice(e.target.value)}
/>
<button type="submit" onClick={onClick}>
Set
</button>
</div>
);
}