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
Related
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
Currently, my react/nextjs dynamic list is not updating correctly, I've given an array to map so it'll show a new row on frame update since it's stored on useState, Usually, the issue is with the key of the list that is not unique, but my key is unique
Heres my code
const [allSelectedMaterials, setAllSelectedMaterials] = useState([]) // This variable stores a javascript object into the array
{console.log('-- Updated --')}
{allSelectedMaterials.map((material, i) => {
const key = Object.keys(material).toString()
console.log(`${i} - [${key}] ${material}`)
return (
<div key={key}>
<Row className='align-items-center'>
<Col xs='auto'>
<h6>{material[key].name}</h6>
</Col>
<Col>
<Button variant='danger' className='mb-1' onClick={() => handleDeleteMaterial(key)}>
Remove
</Button>
</Col>
</Row>
<InputGroup>
<InputGroup.Text>
<Image src={material[key].image} className={`${styles.allMaterialsImage}`} />
</InputGroup.Text>
<Form.Control type='number' min={1} ref={(e) => (selectedMaterials.current[i] = e)} required />
</InputGroup>
<div className='mt-1' />
</div>
)
})}
The problem is after I added the first item on the list and adding a new one it won't update the view, here's the console output
And here's me adding a second entry to the list
It clearly says on the log that the array (stored in useState) is updated but it's not changing the view it's still the same as the previous one. But if I reupdate the frame by updating any useState variable it updated the list
Update:
Here's my code for adding new material
(loadedMaterials is just a list of materials that is retrieved from an API)
const handleAddSelectedMaterial = () => {
loadedMaterials.map((material) => {
const key = Object.keys(material)
if (key == currentSelectedMaterial) {
let _material
if (allSelectedMaterials.length > 0) _material = allSelectedMaterials
else _material = []
_material.push({ [material[key].id]: material[key] })
setAllSelectedMaterials(_material)
}
})
}
Try replacing
from
_material.push({ [material[key].id]: material[key] })
setAllSelectedMaterials(_material)
to
_material.push({ [material[key].id]: material[key] })
setAllSelectedMaterials([..._material])
Thank you everyone for the input and responses, but I've managed to solve this issue by redoing how the form & dynamic list work and it's working perfectly now.
If anyone is wondering I just basically follow this person implementation on a dynamic list
https://www.cluemediator.com/add-or-remove-input-fields-dynamically-with-reactjs
I am a beginner and I am trying to create a recipe app. I managed to set up an API that gives an Array of 10 objects each time I search for a meal like so.
I access the elements of each recipe using a map
{recipes.map(recipe =>(
<RecipeCard
key={recipe.recipe.label}
title ={recipe.recipe.label}
calories={recipe.recipe.calories}
image={recipe.recipe.image}
ingredients={recipe.recipe.ingredients}
/>
))}
Here is also my Const Recipe Card just for some more context. It functions fine.
const RecipeCard = ({title, calories, image, ingredients}) => {
const round = Math.round(calories);
return(
<div className = {style.recipe}>
<h1 >{title}</h1>
<ol className = {style.list}>
{ingredients.map(ingredient => (
<li>{ingredient.text}</li>
))}
</ol>
<p>calories: {round} </p>
<img className = {style.image} src={image} alt=""/>
<button>Add to Favorites</button>
</div>
)
}
I currently only want to access the information from the first array, but whenever I change recipes.map to recipes[0] it says that function does not exist. How should I go about accessing individual elements from the arrays provided from the API?
You can use .slice(0, 1) to create a shallow copy (a new array with just first element):
{recipes.slice(0, 1).map(recipe =>(
<RecipeCard
key={recipe.recipe.label}
title ={recipe.recipe.label}
calories={recipe.recipe.calories}
image={recipe.recipe.image}
ingredients={recipe.recipe.ingredients}
/>
))}
Or use destructuring:
const [recipe] = recipes // before "return"
// ....
<RecipeCard
key={recipe.recipe.label}
title ={recipe.recipe.label}
calories={recipe.recipe.calories}
image={recipe.recipe.image}
ingredients={recipe.recipe.ingredients}
/>
Or use index:
<RecipeCard
key={recipes[0]?.recipe.label}
title ={recipes[0]?.recipe.label}
calories={recipes[0]?.recipe.calories}
image={recipes[0]?.recipe.image}
ingredients={recipes[0]?.recipe.ingredients}
/>
The ?. is called optional chaining, you can use it to avoid error like Can't Read property of undefined, i.e. when the first element is undefined and you try to read its properties.
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>
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`
}