Pass a multiple arguments from a child props to the parent method - javascript

I am new to react js . Here, what I am trying to do is that , I have a parent component which is like:
onchange(event) {
console.log("function will be callled", event.target.value, event.target.id);
{ (this.props.lowData) && this.props.lowData.Low.length > 0 && this.props.lowData.Low.map(data => (
<LowRow technologies={this.state.technologies} onChange={this.onchange.bind(this)} data={data} key={data.id} />
))}
Here there is a onchnage method I am passing as a props to the child element, which is:
<select className="selectpicker btn btn-labeled btn-start selectId techDrop margin-left-10" onChange={props.onChange}>
<option disabled selected value>None Selected</option>
{props.technologies && <Select techData={props.technologies} options={props.technologyName} />}
</select>
So, Now what I want to do is that, In the child when user changes:
onChange={props.onChange}
this gets called in parent element, so here I also want to pass one more parameter with this like:
onChange = {props.onChange, props.id}so that Parent will get one Id as well, But its not working . And also I tried with the `props.onChange(props.id)` But no luck. Can any one help me with this ?

Parent onchange function will receive id in 2nd argument.
onchange(event, id) {
console.log("function will be callled", event.target.value, id);
}
While calling from child you call like this.
onChange={(e)=> {props.onChange(e, props.id)}}

First thing you are not recommended to bind a function directly in render. Because when you bind a function directly in render your component will render for many reasons like setState, when new props received etc. so every time it renders it will create a new function in webpack generated bundle file so the file size becomes large. so always do binding in constructor
Now regarding your issue. Do map in render directly and pass onChange as a prop down to LowRow component. You need to do something like below to pass a function as a prop and send params to it in child component and access it in parent component. This concept is called callbacks in react.
One more thing never forget to add a key to parent jsx element whenever you generate jsx elements in loop. The key should be a unique id from data. If your data don't conatin unique id then pass index as key like key={"key" +index}
constructor(props){
super(props);
this.onChange = this.onChange.bind(this);
}
onChange(event, id) {
console.log("test", event, id);
}
render(){
const { lowData } = this.props;
return(
<div>
{this.props.lowData && this.props.lowData.Low.map(data => (
<LowRow key={data.id} technologies={this.state.technologies} onChange={this.onChange} data={data} key={data.id} />
))}
</div>
)
}
Select onChange
Here not sure what id are you passing. but you can pass params like how I did in the below code
<select className="selectpicker btn btn-labeled btn-start selectId techDrop margin-left-10" onChange={e => props.onChange(e, id)}>
<option disabled selected value>None Selected</option>
{props.technologies && <Select techData={props.technologies} options={props.technologyName} />}
</select>

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.js acessing component props via e.target

i want to access items desc's to add them to 'cart'.
exactly i would like to change hook value on Item click.
thanks for your time
some code here:
{items.map(
item =>(
<Item src={item.recipe.image}
desc = {item.recipe.label}
price = {`${(item.recipe.label).length}$`}
/>
)
)}
You could pass the value in desc as an argument to the onClick function rather than trying to hack the value of an attribute/prop
{items.map(
item =>(
<Item src={item.recipe.image}
desc = {item.recipe.label}
price = {`${(item.recipe.label).length}$`}
onClick = {(e) => handleClick(e,item.recipe.label)}
/>
)
)}
and on the handleClick function get the second argument as the desc

Why props alone are being used in called React function component?

I was learning React and I came to a point which created confusion. Everywhere I was using props while writing Function components.
I always use props.profile and it works fine. But in one code component, I had to write
const profiles=props; and it worked fine.
I tried using const profiles=props.profile; and also I tried using inside return in 'Card' function component
{props.profile.avatar_url} but both of them failed
Below is my code which works fine
const Card=(props)=>{
const profiles=props; //This I dont understand
return(
<div>
<div>
<img src={profiles.avatar_url} width="75px" alt="profile pic"/>
</div>
<div>
<div>{profiles.name}</div>
<div>{profiles.company}</div>
</div>
</div>
);
}
const CardList=(props)=>{
return(
<div>
{testDataArr.map(profile=><Card {...profile}/>)}
</div>
);
}
Can someone please help me understand why I can't use const profiles=props.profile?
What are the other ways to achieve the correct result?
Your testDataArr might be this,
testDataArr = [{avatar_url:"",name:"",company:""},{avatar_url:"",name:"",company:""},{avatar_url:"",name:"",company:""}]
Now when you do this,
{testDataArr.map(profile=><Card {...profile}/>)}
here profile = {avatar_url:"",name:"",company:""},
and when you do,
<Card {...profile}/>
is equivalent to,
<Card avatar_url="" name="" company=""/>
In child component, when you do this,
const profiles=props;
here props = {avatar_url:"",name:"",company:""}
So you can access it's values,
props.avatar_url
props.name
props.company
But when you do this,
const profiles=props.profile
profile key is not present in {avatar_url:"",name:"",company:""} object and it fails.
OK. Here is the issue, the props object does not contain a profile attribute, but IT IS the profile attribute. Becouse you are spreading the profile variable when you render the Card element (in the CardList), you basically are writing:
<Card avatarUrl={profile.avatarUrl} comapny={profile.comany} />
Instead, you should do
<Card profile={profile} />
and then in your Card component access the data this way
const Card = (props) => {
const profile = props.profile
}
or even simpler
const Card = ({profile}) => {
return <div>{profile.comany}</div>
}

Passing down variable to handler in sub component in ReactJS

I have a AllPersons component, where I want to pass down a callback from my main app.js component, I want it so, I can edit a person, that I'm displaying inside my table.
My issue is that I need the id of the person, in order to change just that one person.
I'm mapping through an array of person objects and adding a button to make the callback
However, I need to pass the id inside to the handler so I can edit just that person
<div className="col-md-6">
<h3>All Persons</h3>
<AllPersons persons={this.state.persons} onEdit=
{this.onEditHandler} id={this.id} />
</div>
//AllPersons.js
{persons.map((person, i) => (
<tr key={i}>
<th>{person.age}</th>
<th>{person.name}</th>
<th>{person.gender}</th>
<th>{person.email}</th>
<a href="/#" onClick= {props.onEdit} id={person.id}>edit</a>
</tr>
//handle method inside App.js
onEditHandler = (event) =>{
event.preventDefault();
console.log("editet")
}
I was considering setting the id as a state, but I think that would be too much,
Use curryng for this case
Define you hander like this
editHandler = id => event => {
// you have id here
}
And use it in JSX
<a href="/#" onClick= {props.onEdit(person.id)}>edit</a>

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