Finding the value of the element clicked in React - javascript

I am using Material Ui for my elements and I have a button which when I click I need to know the value of it so that I can pass it through to the backend to remove it..
My JSX code
for (let i = 0; i < this.state.emails.length; i++) {
emails.push(
<div key={i}>
<TextField style={textField}
autoFocus
floatingLabelText="EMAIL"
type="email"
spellCheck={false}
autoCorrect={"off"}
value={this.state.emails[i]}
onChange={(e) => this.setState({primaryEmail: e.target.value})}
/>
<FlatButton
primary
label="REMOVE EMAIL"
className="userProfile-buttons"
value={this.state.emails[i]}
onClick={this.removeEmailHandler}
/>
</div>
)
}
My js code
removeEmailHandler = (e) => {
console.log(e.target.value)
}

You can change your to
removeEmailHandler = (value) => {
console.log(value)
}
So you can pass in the value in onClick
and onClick={(value)=>this.removeEmailHandler(value) }

You really don't need the value of the button where the removeEmailHandler() method is called. What you need should be in the state, given that it is been set onChange within the TextField component prop.
So the removeEmailHandler() method should basically make an API call with what is in the state to the backend.
removeEmailHandler = (e) => {
// make API call with `this.state.primaryEmail`
}

Related

REACT-HOOKS: How do I store a modifed parameter made by the user?

I have checkboxes and I want to save in useState hooks the modified value made by the user. By default the current state is fixed and the checkbox is filled if my_value === 1, elif 0 unfilled. But if my user decides to uncheck it, how can I store this action. (if unchecked the value is 0).
Same idea with dropdown, the default value is fixed. The user can change the Taste( Good/Medium/Bad)or the Comments ((0/4....4/4)).
For now I get only the current state.
export default function Display() {
...
//For my checkboxes
const [availability, setAvailability] = useState(item.values[0].availability)
...
const [trust, setTrust] = useState(item.values[0].trust)
//For my dropdowns
const [taste, setTaste] = useState(item.taste)
...
const [comments, setComments] = useState(rule.comments)
function Checkbox({ value }) {
const [checked, setChecked] = useState(value);
return (
<label>
<input
type="checkbox"
checked={checked}
onChange={() => setChecked(checked => !checked)}
/>
{value}
</label>
);
}
return (
<div>
<div>
Availability : <Checkbox value={!!availability} />
</div>
....
<div >
Taste : <Dropdown style={styles.select} options={TASTE} defaultValue={LIKELIHOOD.find((t) => t.label === item.taste)} />
</div>
...
</div >
);
}
This isn't so much a hooks problem as a "where do I store my state" problem. So far I don't see any place in your implementation to store the users choices. Either the MenuItemDisplay component needs to maintain that state, or it needs to receive it from a parent component. Either way, that state (containing user choices) will need to be passed down (along with update functions) into the checkbox component as the value of a 'checked' prop, and the update functions for that state should be passed as (and adapted to) the checkbox 'onToggle' (or similar) prop

React component not sending variable value with onChange event

I am trying to display more than one task using the same react component and a map function. The components is supposed to upload a file and display the file that has been upload or is uploading with an onChange event, an onSubmit event will be added later to send the file to the back-end. Since the component is being dynamically rendered with an onChange event I am sending the li key as a parameter then only rendering the filename to the li that matches based on the key. The issue I am currently having is when I send the key in the onChange the value is not getting to the function. I have even tried setting a state for the key and then pulling that into the function but I get back undefined I have tried 100 other things as well and either get back undefined or 0. This is my first post on here and I am also just a junior dev so I may be missing info needed here if so please let me know.
Here is the code
const onChange = (e, index) => {
setFilename(e.target.files[0].name)
setArrFiles([...arrFiles, {key:index, file:e.target.files[0].name} ])
}
const displayTask = (index) => {
let upload = []
arrFiles.forEach(el => {
if(el.key === index) {
upload.push(el.file)
}
})
return upload.map((file) => (
<li key={index}>{file}</li>
))
}
{database.map((task, index) => (
<li key={index}>
<p>{index}</p>
<div className="userPortal__tasksContainer">
<div className='userPortal__tasksHeader'>
<p className='userPortal__tasksHeaderTitle'>{task.taskTitle}</p>
<p className='userPortal__tasksHeaderInfo'>{task.taskMessage}</p>
</div>
<div className='userPortal__tasksBodyButtons'>
<form className='userPortal__fileUpload'>
<input className='userPortal__inputButton' multiple id='file' type="file" onChange={e => onChange(e, index)}/>
<label htmlFor='file'>Choose File</label>
</form>
<button className='userPortal__tasksBodyButton green'>Task Complete</button>
</div>
<p id='userPortalFooterTitle'>Successfully Uploaded</p>
<div className='userPortal__footer'>
<ul>
{displayTask(index)}
</ul>
</div>
</div>
</li>
))}
The issue here was like a dummy I hard coded the input ID so when referencing the input field it would only get the hard coded value instead of the index of the component.
Here is the updated form.
<form className='userPortal__fileUpload'>
<input className='userPortal__inputButton' multiple id={index} type="file" onChange={(() => (e) => onChange(e, index))()}/>
<label htmlFor={index}>Choose File</label>
</form>
No Do It Like This
const onChange = (e, index) => {
setFilename(e.target.files[0].name);
// Okay You Need To Filter The State In Order To Get The Object With THe Current Index
// Set The File Value Of The Object To e.target.files[0].name
setArrFiles((state) => {
const allFiles = state;
const currentFile = allFiles.filter(
(file) => parseInt(file.key) === parseInt(index)
)[0];
// i converted it to an integer just to prevent further bugs
currentFile.file = e.target.files[0].name;
return [allFiles];
});
};

How to use useEffect inside a handler or vice versa?

I have a function which is handler of onChange and get value of input
and also I have a function for search in an array using searched value coming from that input
and render a component that contains searched array as props.
But I have a problem
when I search it works but after second letter and when the input is empty it shows the last search.
I think it should be handled with useEffect but I dont how to solve or may be I am wrong
I need help to correct that
thanks for your help.
these are my code :
getting search value part and sending as argument :
function BasePage({handleClick, handleSearch }) {
const [searchValue, setSearchValue] = useState('');
useEffect(() => {
function handleChangeSearchInput(e) {
const newSearchValue = e.target.value;
setSearchValue(newSearchValue);
handleSearch(searchValue);
}
})
return (
<div>
<fieldset>
<legend>Search</legend>
<input
value = {searchValue}
onChange = {handleChangeSearchInput}
placeholder = "Enter name to search"
type = "text"
/>
<button onClick={() => handleClick('add-record-form')}>Add</button>
</fieldset>
<br />
{searchValue.length > 0 && <SearchRecord record = {searchValue} />}
</div>
);
}
and this filters in parent component :
function handleSearch(searchValue) {
const searchedTerm = contacts.filter(contact => (contact.name.toLowerCase().includes(searchValue.toLowerCase())));
setSearchTerms(searchedTerm);
}
and I use map to show them .
You shouldn't need useEffect for this. Just have the handler deal with both the setting of state, and the updating.
function handleChangeSearchInput(e) {
const newSearchValue = e.target.value;
setSearchValue(newSearchValue);
handleSearch(newSearchValue);
}

(react.js) why losing value of the fields and why is re-rendering?

what would be the reason I lose the value on the inputs when I try to add another one,?
in the component I set the useState with an array of an empty string, and when I click the add button it ads another slot in the array, but every time I add a field, the value in the rest of the form is reset and lost. I believe the app is re-rendering.
const IngridientsInputField = () => {
function newIngridient(event) {
event.preventDefault();
setStateIngridients([...stateIngridients, ''] )
setStateCounter(stateCounter +1)
}
return (
<div className="ingridients">
<h3>number of ingridients {stateCounter}</h3>
{ stateIngridients.map(() => (
<input type="text" name="ingridient" title="ingridient" placeholder={`ingridient (example: pineapple)`} />
))
}
<button onClick={newIngridient}>add + </button>
</div>
)
};

creating elements in React

I don't understand how elements are created in React.
I have some code below where the goal is to create elements on a form submit using a value from a refs - so for every submit in a form, it creates a new <h1> tag with the content of the textbox inside of it. A sample of what I'm trying to do looks like:
...
addHeader(e) {
e.preventDefault();
const newHeader = this.refs.post.value;
var newpost = React.createElement("h1", {
type: "text",
value: newHeader
});
}
...
render() {
return (
<div className="form-section">
{ newPost }
<form onSubmit={this.addHeader.bind(this)}>
<input id="input-post" type="text" placeholder="Post Here" ref="post" />
<input type="submit" value="Submit" />
</form>
<button className="form-section__submit" onClick={this.clearFields.bind(this)}>Clear All</button>
</div>
);
}
Basically my thinking is in my addHeader() function I'm assigning a variable of newPost to the method and calling it within my component. This code is causing 2 errors:
33:9 warning 'newpost' is assigned a value but never used no-unused-vars
49:13 error 'newPost' is not defined no-undef
What I don't understand, is (from what I can see) I am assigning a value to that variable and also using it in the component that I am rendering... along with that, I don't understand this error message. How can something be assigned a value but be undefined at the same time...? Is it because it's in the wrong scope? How do I declare where the new element is rendered specifically in the component?
I read the documentation but it doesn't give a clear answer as to how to control where in the component the new element is rendered.
Made some changes to your code. You're going to want to initialize component state in your constructor. In your addHeader method you will use this.setState to update the state of the component with a new posts value including the value of this.input. I changed your ref on the input an actual ref. You take the element and store on this. Every time you add a new post you will get a new <h1> with the value of the textarea.
...
addHeader(e) {
e.preventDefault();
this.setState((prevState, props) => {
return { posts: [ ...prevState.posts, this.input.value ] };
});
}
...
render() {
const { posts } = this.state;
return (
<div className="form-section">
{ posts.map( text => <h1>{ text }</h1> ) }
<form onSubmit={this.addHeader.bind(this)}>
<input id="input-post" type="text" placeholder="Post Here" ref={ el => this.input = ref } />
<input type="submit" value="Submit" />
</form>
<button className="form-section__submit" onClick={this.clearFields.bind(this)}>Clear All</button>
</div>
);
}
As an aside: Binding functions in the render method of react components will cause a performance hit. There is no need to re-bind the this context of the function on every render. this.clearFields.bind(this) should become this.clearFields and you will need to add this.clearFields = this.clearFields.bind(this) to your constructor. You do not need to bind functions that are not used as callbacks.
You're going to want to do the same thing for this.addHeader.bind(this).

Categories

Resources