how can I remove part of data from state in react.js - reactjs

I create and add some data to my selecetFile2 state / then I want to delete some part of that selecetFile2 state by any event- just guide for function.
const [selectedFile2, setSelectedFile2] = useState([]); //my state for data
const [isFilePicked2, setIsFilePicked2] = useState(false); //just controll for page
this function for control data
const changeHandler2 = (event) => {
setSelectedFile2([...selectedFile2,event.target.files[0]]);
setIsFilePicked(true);}
const multi_img = ()=>{ //It's for input dialog box
document.getElementById("multi_img").click();}
this my main code
<input type="file" onChange={changeHandler2} title="ali ali" id="multi_img"
name="img" accept="image/*" style={{display:'none'}} />
<div><BsFillPlusSquareFill onClick={multi_img} /> //input control by this
{
isFilePicked2 &&
selectedFile2.map(item => <img key={v4()} src={URL.createObjectURL(item)} />)
//this my Item I want to delete for example by click
//I just need function
}

Here you go
<input
type="file"
onChange={changeHandler2}
title="ali ali"
id="multi_img"
name="img"
accept="image/*"
style={{ display: "none" }}
/>
<div>
<BsFillPlusSquareFill onClick={multi_img} /> //input control by this
{
isFilePicked2 &&
selectedFile2.map((item) => (
<img key={v4()} src={URL.createObjectURL(item)} onClick={ () => {
setSelectedFile2(selectedFile2.filter(i => i !== item))
}} />
))
//this my Item I want to delete for example by click
//I just need function
}
</div>

By using useState, you can not directly update or modify the state. Whenever you wanted to modify or update the state you have to do it using the set[nameofstate]. In your case.
whenever you want to update selectedFile2 you have to pass the new value for seletedFile2 to setSelectedFile2(newValueForSelectedFile2).
for more information and examples please visit documenation

Related

How to set value in input field to empty by click on a button in react js?

How to set value in input field to empty by click on a button in react js ?
I thought it is an easy step to empty an input field by click on button, though it is easy but my code is not working. I m using Ant design onSearch input field. I want that when I click on CloseCircleOutlined button, the input field must be set to empty. Kindly help me to solve this issue.
Here is my code:
const [search, setSearch] = useState("");
const handleChange = (value) => {
setSearch(value);
}
const onSearch = () => {
if(search){
mutation()
setisSearched(true);
}
setCurrentPage(1);
}
const handleCloseButton = (e)=>{
setSearch(" ")
}
<SearcI want thath
enterButton="Search"
size="large"
placeholder="Search Product"
className="search_bar"
onSearch={onSearch}
onChange={(e) => handleChange(e.target.value)}
/>
<Text>Showing results for {`"${search} "`} <CloseCircleOutlined onClick={handleCloseButton}/></Text>
I guess you already set to empty string but you do not use that parameter in your search component. You should use value
<Search
enterButton="Search"
size="large"
placeholder="Search Product"
className="search_bar"
onSearch={onSearch}
onChange={(e) => handleChange(e.target.value)}
value={search}
/>

Show an input field corresponding to radio button selection

const next = useRef(false);
const [validate,setValidate] = useState(false);
const [data, setData] = useState(healthform);
return (
<div>
<div class="hQ">
Have you travel anywhere before?
</div>
<div class="hA">
<Radio name={"travAny"} value={data.traAny} onChange={(val,name,isValid)=>{
data[name]=val;
valids[name]=isValid;
}} />
</div>
{(data.traAny && data.traAny !== "0") && <Input placeHolder="If yes, please list all countries: " value={data.traAnyDet} name="traAnyDet" onChange={(val, name, isValid) => {
data[name] = val;
valids[name] = isValid;
}} />}
</div>
);
I want to only display the input field as we select yes on radio button. I tried. But it doesn't show on the time that we pick yes. It only displays when it is already yes.
Looking at your code. I think the problem is with how you update the values. You are directly mutating the state object instaed of updating it using the setState function.
I think changing the way you update the data to a solution like the one below will fix your issue:-
const [data, setData] = useState(healthForm)
<Radio name={"travAny"} value={data.traAny} onChange={(val,name,isValid)=>{
setData(prevData=>({...prevData, [name]:val, }))
}} />
You should do the same for the valids.

How to add TextArea while clicking on image using React JS?

###This is how the code looks like ###
const message = () => {
console.log("Hello World!")
}
return(
<label htmlFor="myInput" ><ShoppingBagIcon style={{width:'26px'}} type="shoppingbag" /></label>
<input id="myInput" type="text" style={{display:'none'}} onClick={message} />)}
export default message
You could use a hook const [shown, setShown] = useState(false)
and render the TextArea based on the value of the hook.
An oversimplified example:
const [shown, setShown] = useState(false)
return (
<>
<button on:click={() => setShown(!shown)}/>
{shown ? <TextArea/> : <WithoutTextArea/>}
</>
);
You can use an extra state say, toggleView in your project. And when a user clicks the image you can set the value true or false. Based on that you can show the textField or not. What I meant is
import React,{useState} from 'react'
const message = () => {
const [showText,toggleShowText] = useState(false);
console.log("Hello World!")
const toggleTextField = () => toggleShowText(!showText)
return(
<div>
<label htmlFor="myInput" ><ShoppingBagIcon style={{width:'26px'}} type="shoppingbag" onClick ={()=>toggleShowText(!showText)}/></label>
{
showText ? (
<input id="myInput" type="text" onClick={message} />
) : (<div/>)
}
</div>
);
}
export default message;
Also in your code, the curly braces are not formatted, I did that Above example.
Also, you can use the ternary operator inside the HTML tag.
<input id="myInput" type="text" style={showText ? {display:'none'}: {display:'inline'}} onClick={message} />
or
style={{display: showText ? 'block' : 'none'}}
I Think the best way of doing hiding or showing an HTML element is using ref
import useRef from react
import { useRef } from "react";
Create a ref
const inputRef = useRef();
Use it in the input or textarea
<input
ref={inputRef}
id="myInput"
type="text"
style={{ display: "none" }}
/>
Now you can change it's any style like this
inputRef.current.style.display = "block";
Why ref?
Because it do not re-render the component. If you use state it will cost a render but using ref it won't
here is the solve
Updated
If you want to hide any elements you can do that like this bellow
ref_variable.current.style.display = 'none'
So when and which element you want to hide just make the display none using the ref.
For example if you want to hide the textarea after input. Just do that.

Discordance between component state and its props

I am making a basic drag and drop utility where you can drag and recombine the position of three cards in React.
I dont know why but there seems to be discordance between the actual data on the parents state and its child. After some refactoring following users input, things are as this:
onDrop = (event) => {
event.preventDefault();
event.stopPropagation();
const newData = this.props.getDraggedCard(); //gets the data actually being dragged around
let receiverCard = Object.assign({}, this.state) //backup of the previous state
this.setState({
_id: newData._id,
text: newData.text,
title: newData.title,
subtitle: newData.subtitle,
image: newData.image
}, () => { this.props.onDropParentData(receiverCard) })
}
this function is on every child component, which are the items actually to be moved around.
The parent component, which stores and saves the data:
onDropParentData = (receiverCard) => {
let {slideInformation}=this.state; //the state where all the data is
let draggedCard = this.state.draggedCard; //the data being dragged
const indexDragged= slideInformation.findIndex((element)=>element.id===draggedCard.id)
const indexReceiver= slideInformation.findIndex((element)=>element.id===receiverCard.id)
let draggedCardIdStorage = this.state.draggedCard.id;
draggedCard.id = receiverCard.id;
receiverCard.id = draggedCardIdStorage;
slideInformation.splice(indexDragged,1,draggedCard);
slideInformation.splice(indexReceiver,1,receiverCard);
this.setState({slideInformation});
}
with this actual code, the state holds the correct information but when dragging and dropping, items dont switch between positions as desired, only the dropped item gets its new position.
The render method on the parent is:
{this.state.slideInformation.map((slide,index) => {
return (
<CardFormBody
getDraggedCard={this.getDraggedCard}
key={index}
onDropParentData={this.onDropParentData}
onDrag={this.onDrag}
slide={slide}
onDragOver={this.onDragOver}
setFormData={this.setFormData}
/>
)
})}
And every CardFormBody is
<div draggable onDrag={(event) => { this.props.onDrag(event, this.state) }} className="newsCard" name={this.state.id}>
<label>Título</label>
<input name={this.state.id} onChange={this.handleTitleChange} value={this.props.slide.title} />
<label>Subtítulo</label>
<input name={this.state.id} onChange={this.handleSubtitleChange} value={this.state.subtitle} />
<label>Texto</label>
<textarea onDragOver={this.props.onDragOver} onDrop={this.onDrop} name={this.state.id} onChange={this.handleTextChange} value={this.state.text} />
<button type="button" name={this.state.id} onClick={this.handleImgChange}>Añadir Imagen</button>
<div className="imageWrapperForm">
<img alt="preview" name={this.state.id} className="previewImg" src={this.state.image} />
</div>
</div>
Ciao, can you provide more code? How you pass data from child to parent? Anyway I think the misalignment between children and parent data could be on how you pass them.

how react programmatically focus input

I'm trying to implement a very simple use case, a UI feature, where:
There is a label with some content in it
If clicked, a text input replaces it with the content of label available
User can edit the content
When enter is pressed, the input hides and label is back with updated content
I could get finally all correct (in fact with a MongoBD backend, redux, etc.), and the only thing I couldn't ever do (paying a complete day in googling and reading S.O.F similar posts) was this:
When my text input appears, I can't transfer focus to it! First I tired this way:
<div className={((this.state.toggleWordEdit) ? '' : 'hidden')}>
<input id={this.props.word._id} className="form-control"
ref="updateTheWord"
defaultValue={this.state.word}
onChange={this.handleChange}
onKeyPress={this.handleSubmit}
autoFocus={this.state.toggleWordEdit}/></div>
<div className={((this.state.toggleWordEdit) ? 'hidden' : '')}>
<h3 onClick={this.updateWord}>
{this.state.word}</h3>
</div>
but autoFocus sure didn't work (I "guess" because the form is rendered, but in hidden state, making autoFocus useless).
Next I tried in my this.updateWor, many of suggestions I found on google and S.O.F.:
this.refs.updateTheWord.focus();
which together with similar suggestions all didn't work. Also I tried to fool React just to see if at all I can do something! I used real DOM:
const x = document.getElementById(this.props.word._id);
x.focus();
and it didn't work either. One thing I even could not understand to put into word is a suggestion like this:
having ref as a method (I "guess")
I didn't even try it because I have multiples of these components and I need ref to further get value of, per component, and I couldn't imagine if my ref is not named, how I could get the value of!
So could you please give an idea, helping me to understand that in case I'm not using a Form (because I need a single input box replacing a label) how I could set its focus when it's CSS (Bootstrap) class is losing 'hidden' please?
The way you have used refs is not the most preferred way or else its not the best practice anymore . try some thing like this
class MyClass extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
this.textInput.current.focus();
}
render() {
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Set Focus"
onClick={this.focus}
/>
</div>
);
}
}
Update
From React 16.3 upwards you can use the React.createRef() API
class MyClass extends React.Component {
constructor(props) {
super(props);
// create a ref to store the textInput DOM element
this.textInput = React.createRef();
this.focus = this.focus.bind(this);
}
focus() {
// Explicitly focus the text input using the raw DOM API
// Note: we're accessing "current" to get the DOM node
this.textInput.current.focus();
}
render() {
// tell React that we want to associate the <input> ref
// with the `textInput` that we created in the constructor
return (
<div>
<input
type="text"
ref={this.textInput} />
<input
type="button"
value="Set Focus"
onClick={this.focus}
/>
</div>
);
}
}
From React 18.xx upwards you can use the useRef Hook
import React, { useRef } from "react";
export const Form = () => {
const inputRef = useRef(null);
const focus = () => {
inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<input type="button" value="Set Focus" onClick={focus} />
</div>
);
};
Just add autofocus attribute to the input. (of course in JSX it is autoFocus)
<input autoFocus ...
useFocus hook
// General Focus Hook
const useFocus = (initialFocus = false, id = "") => {
const [focus, setFocus] = useState(initialFocus)
const setFocusWithTrueDefault = (param) => setFocus(isBoolean(param)? param : true)
return ([
setFocusWithTrueDefault, {
autoFocus: focus,
key: `${id}${focus}`,
onFocus: () => setFocus(true),
onBlur: () => setFocus(false),
},
])
}
const FocusDemo = () => {
const [labelStr, setLabelStr] = useState("Your initial Value")
const [setFocus, focusProps] = useFocus(true)
return (
<> {/* React.Fragment */}
<input
onChange={(e)=> setLabelStr(e.target.value)}
value={labelStr}
{...focusProps}
/>
<h3 onClick={setFocus}>{labelStr}</h3>
</>
)
}
For a more complete demo click here.
In addition to the previous answers, I've added setTimeout to make it work
handleClick() {
if (this.searchInput) {
setTimeout(() => {
this.searchInput.focus();
}, 100);
}
}
where searchInput is the jsx ref of the input
<input
type="text"
name="searchText"
ref={(input) => { this.searchInput = input; }}
placeholder="Search" />
and the handleClick() is an onClick handler to any element
#BenCarp's answer in typescript
Pass the inputRef to an input and just call setFocus to set the focus to it.
export const useInputFocus = (): [MutableRefObject<HTMLInputElement | undefined>, () => void] => {
const inputRef = useRef<HTMLInputElement>();
const setFocus = (): void => {
const currentEl = inputRef.current;
if (currentEl) {
currentEl.focus();
}
};
return [inputRef, setFocus];
};
Use componentDidUpdate method to every time update the component
componentDidUpdate(prevProps, prevState) {
this.input.focus();
}
You can use "useRef" hook and make a reference to your input control, then use your reference.current.focus()

Resources