how to use single save bar on multiple input fields - react js - javascript

image of save bar and input fields
I am new to react, I have a problem I want to display a Savebar on [onChange] on a number of input fields.
When input length is greater than 0 then it will show, but I have multiple input, my problem is when I type in 2 0r 3 fields it shows multiple time, but I want to show it by conditions that, when it is already open then it cannot open again. thanks in advance.
const [showBanner, setShowBanner] = useState(false);
const handelBanner = (e) => {
if (e.target.value.length > 0) {
setShowBanner(true)
}else{
setShowBanner(false)
}
}
return:
{showBanner ? (
<> save bar </>
) : null}

You can save all the input value to the state. Watch all input change and do your conditional logic in useEffect. Like this:
const [showBanner, setShowBanner] = useState(false);
const [input1, setInput1] = useState('');
const [input2, setInput2] = useState('');
useEffect(() => {
if () { // put your condition
setShowBanner(true);
} else {
setShowBanner(false)
}
}, [input1, input2])
const handleChangeInput1 = e => setInput1(e.target.value);
const handleChangeInput2 = e => setInput2(e.target.value);

Related

Remove item from localStorage after onClick and don't show again anymore after browser refresh in React app

In my React app I am showing a banner yes or no, based on React state and some values set in localStorage.
After close button is clicked, it's state showBanner is saved to localStorage and doesn't show the banner anymore
After 2 times using a page url in the React app with query param redirect=my-site it doesn't show the banner anymore:
import queryString from 'query-string';
const location = useLocation();
const queryParams = queryString.parse(location.search);
const [showBanner, setShowBanner] = useState(true);
const handleClick = () => {
setShowBanner(false);
localStorage.removeItem('redirect');
};
const hasQp = queryString
.stringify(queryParams)
.includes('redirect=my-site');
const initialCount = () => {
if (typeof window !== 'undefined' && hasQp) {
return Number(localStorage.getItem('redirect')) || 0;
}
return null;
};
const [count, setCount] = useState(initialCount);
const show = showBanner && hasQp && count! < 3;
useEffect(() => {
const data = localStorage.getItem('my-banner');
if (data !== null) {
setShowBanner(JSON.parse(data));
}
}, []);
useEffect(() => {
localStorage.setItem('my-banner', JSON.stringify(showBanner));
}, [showBanner]);
useEffect(() => {
let pageView = count;
if (pageView === 0) {
pageView = 1;
} else {
pageView = Number(pageView) + 1;
}
if (hasQp && showBanner === true) {
localStorage.setItem('redirect', String(pageView));
setCount(pageView);
}
}, []);
This is working fine (when you see some good code improvements let me know :) ).
But as soon the user clicks the close button I don't want the localStorage item redirect no longer appears. Now after refreshing the page it appears again.
How do i get this to work?
If this is executing when the page loads:
localStorage.setItem('redirect', String(pageView));
Then that means this is true:
if (hasQp && showBanner === true)
The hasQp value is true, which means this is true:
const hasQp = queryString
.stringify(queryParams)
.includes('redirect=my-site');
And showBanner is true because it's always initialized to true:
const [showBanner, setShowBanner] = useState(true);
It's not 100% clear to me why you need this state value, but you could try initializing it to false by default:
const [showBanner, setShowBanner] = useState(false);
But more to the point, I don't think you need this state value at all. It's basically a duplicate of data that's in localStorage. But since both state and localStorage are always available to you, I don't see a reason to duplicate data between them.
Remove that state value entirely and just use localStorage. An example of checking the value directly might be:
if (hasQp && JSON.parse(localStorage.getItem('my-banner')))
Which of course could be refactored to reduce code. For example, consider a helper function to get the value:
const showBanner = () => {
const data = localStorage.getItem('my-banner') ?? false;
if (data) {
return JSON.parse(data);
}
};
Then the check could be:
if (hasQp && showBanner())
There are likely a variety of ways to refactor the code, but overall the point is to not duplicate data. In thie case a value is being stored in localStorage instead of React state because it needs to persist across page loads. Just keep that value in localStorage and use it from there.

How can I limit the input tag to only 10 Commas?

You need an input custom that limits you to 10 commas.
When it is 10, it should be possible to modify it.
Currently, the input event works faster, so additional commas are added so it cannot be edited.
my code
// input props
value={relationSearch}
onChange={(e) => handleOnChangeInput(e)}
onKeyPress={handleKeyPress}
//callbackfunction
const relationCallbackFunction = {
handleOnChangeInput: (e) => {
setRelationSearch(e.target.value);
},
};
// input event area
const handleOnChangeInput = (e) => {
relationCallbackFunction.handleOnChangeInput(e);
};
const handleKeyPress = (e) => {
const currentStr = relationSearch.split(',');
console.log(e.target.value);
if (currentStr.length > 11) {
e.target.value ='';
}
};
you could do this a couple of ways, but here is a simple solution. The important part here is to ensure you set your input to a controlled input, where you provide the value from react.
We need a function which will implement your logic. It should take in a string and the total number of commas you want, and limit that string to the comma amount.
Below is a very simple function that does this. It splits the string using commas, ensures the result array stays at 10 length, and returns a joined string from the resultant array.
function ensureCommas(str, commas = 10) {
const commaArray = str.split(',');
const reduced = commaArray.slice(0, commas);
return reduced.join(',');
}
Now to use it. Here is a very simple App component which keeps the input value in state and provides this state value to the input, and has an onChange event handler which calls the above function on every key press
import { useState } from "react";
import "./styles.css";
function ensureCommas(str, commas = 10) {
const commaArray = str.split(",");
return commaArray.slice(0, 10);
}
export default function App() {
const [value, setValue] = useState("");
const onInputChange = (e) => {
const inputVal = e.target.value;
const newInputVal= ensurecommas(inputVal , 10);
setValue(newInputVal);
};
return (
<div className="App">
<input value={value} onChange={onInputChange}></input>
</div>
);
}
CodeSandbox
Remove the handleKeyPress function from the input props and update the relationCallbackFunction object.
const relationCallbackFunction = {
handleOnChangeInput: (e) => {
let value = e.target.value;
const currentStr = value.split(",");
if (currentStr.length <= 10) {
setRelationSearch(value);
}
}
};

React hooks add mapped checkbox values to array or remove it

I tried some solutions on the net but cant fix it so i need to ask. I have checkboxes which is mapped in render. I want to add the values of the checkboxes to array state if checked or remove the value if unchecked. Thanks for helps Things i tried ;
My jsx ;
{props.edit && <input type="checkbox" value={props.id} onChange={(e) => setDeleteId(e)}/>}
Functions ;
const [deleteId, setdeleteId] = useState([]);
const setDeleteId = (e) => {
setdeleteId([...deleteId, e.target.value]);
}
useEffect(() => {
console.log(deleteId);
}, [deleteId])
Your event handler looks like it's always just adding the checkbox id to the state - you need to also remove it when the checkbox gets unchecked, e.g. -
const [selected, setSelected] = useState([]);
const handleChange = event => {
const { checked, value } = event.currentTarget;
setSelected(
prev => checked
? [...prev, value]
: prev.filter(val => val !== value)
);
};
Here is a demo on StackBlitz showing how it all fits together.

How to reset a select field onChange

I have a dropdown select component that is populated by what is selected from a set of buttons. Before a selection from the button list is made the dropdown has no choices. But I have created an issue where if a button is selected then another is selected the dropdown still holds the value from the previous selection even tho that item is not suppose to be in the list of options in the drop down. I am trying to figure out a way to reset or clear the selection:
const [location, setLocation] = useState("");
const [thvchecked, setThvChecked] = useState(false);
const [pvchecked, setPvChecked] = useState(false);
const [osvchecked, setOsvChecked] = useState(false);
let emCodeOptions = [];
if (location === "telehealthVisit") {
emCodeOptions = telehealthVisitEMCode;
} else if (location === "telephoneVisit") {
emCodeOptions = telephoneVisitEMCodeChoices;
} else if (location === "onSiteVisit") {
emCodeOptions = onSiteVisitEMCodeChoices;
} else {
emCodeOptions = [];
}
const handleEMCodeChange = (selected) => {
props.onUpdate("emCode", selected.value);
};
const onLocationSelection = (event) => {
let loc = event.target.name;
if (loc === "telehealthVisit") {
setLocation("");
setThvChecked(!thvchecked);
props.onUpdate("visitLocation", loc);
} else if (loc === "telephoneVisit") {
setLocation("");
setPvChecked(!pvchecked);
props.onUpdate("visitLocation", loc);
} else if (loc === "onSiteVisit") {
setLocation("");
setOsvChecked(!osvchecked);
props.onUpdate("visitLocation", loc);
}
setLocation(loc);
};
I though I could do this by resetting the state in the onLocationSlection function but this doesnt seem to work beyond the first time I change my selection.
React doesn't call render method each time u setLocation . It will accumulate the values and smartly call the render with the last value. So setLocation to '' doesn't have the desired effect.
This piece of code looks logically correct to me. Are you updating arrays telehealthVisitEMCode, telephoneVisitEMCodeChoices else where?

REACT Dynamic checkboxes

Purpose: I want to create any # of rows containing any # of checkboxes that will be handled by a useState hook.
Problem: Page becomes frozen / constant loading state with nothing showing. No console logs, and debugger doesn't even start. React usually will prevent endless loops of updates. But in this case it didn't get caught.
What I've tried:
console.logs (nothing gets outputted)
debugger statements (nothing
gets paused)
Cant do much bc of frozen page.
CODE:
const CreateCheckboxes = ({ rows, cols }) => {
const classes = useStyles()
const [checked, setChecked] = useState({})
const [isLoaded, setIsLoaded] = useState(false)
//temp initializer
let state = {};
//configures state based on unique checkbox name.
const handleChange = (e) => {
const value = {
...checked,
[e.target.name]: e.target.checked,
}
setChecked(value)
};
//Helper function
const createBoxes = (row, col) => {
let rowArr = [];
for (let i = 0; i < row; i++) {
let checkboxArr = []
for (let j = 0; i < col; j++) {
checkboxArr.push(
<Checkbox
name={`row-${i}-checkbox-${j}`} //unique identifier in the state.
checked={checked[`row-${i}-checkbox-${j}`]}
onChange={(e) => handleChange(e)}
/>
)
//store temp state so that react useState is given a list of initialized 'controlled' states.
//react deosnt like undefined states.
state[`row-${i}-checkbox-${j}`] = false;
}
rowArr.push(
<div className={classes.row}>
<Typography>{`Sound ${i}`}</Typography>
{/* JSX array */}
{checkboxArr}
</div>
)
}
// JSX array
return rowArr
}
//output as a jsx array of 'x row divs' contiaining 'y checkboxes'
const sequenceData = createBoxes(rows, cols)
useEffect(() => {
setChecked(state)
setIsLoaded(true)
}, [])
return isLoaded && (
<>
{sequenceData}
</>
);
}
Solution: Check your loop conditions. Inner loop set to i instead of j.
yes, but I think that component doesn't need to have state various.
I tried to create one. You can check it out following when you have time to see :)
https://codesandbox.io/s/stackoverflow-dynamic-checkboxes-5dh08
Solution: Check your loop conditions. Inner loop set to i instead of j.

Categories

Resources