Getting Cannot set property of undefined Reactjs - reactjs

I am new to react and I need your help.
I have shared a sandbox link, In that everything works perfectly. But when we add couple new row(by clicking + at rightmost columns of the row) then if we remove some row(by clicking - at rightmost columns of the row) and then again add a new row then edit that row cell I am getting Cannot set property error. I know I have to do some changes in the handleDelete function but not getting what exactly to do. So is anyone experts here, please help me out.
And regarding Icon except the last row every other row should have - icon.
Thank you. Comment if you need any clarification.
Sandbox link: https://codesandbox.io/s/suspicious-microservice-qd3ku?file=/index.js

render method actually passes third argument which is actually an id of your component, in your case you don't recalculate the id and that is why your dataSource[key] tries to access key that doesn't exist in dataSource anymore.
render: (text, record, id) => (
<Input
{/* ... */}
onChange={e => this.onChange(e, id)}
/>
)
Here I updated your codesandbox https://codesandbox.io/s/angry-proskuriakova-6f2u0?file=/index.js:1095-1109
Please let me know if you have any questions.

Related

Multi select with controlShouldRenderValue set to true not working in Table

I have a table who's header contains a row of selects. I am trying to display the selections under their respective selects however the selections only show under one of the selects. Im not sure whats going wrong here.
I have a working example here: https://codesandbox.io/s/table-with-multiselcts-fwhsus?file=/src/App.js
In my code the selections are updating underneath the first select when I change any one of the selects. Can anyone explain this?
You used the same onChange callback.
The problem is in the parameters of this function.
field is not a string, it's an object.
So in the switch statement, only default case is executed.
It would be better to set onChange callback respectively.
onChange={e => setLocation(e.target.value)}
onChange={e => setPractice(e.target.value)}
...

React keeps children from previous render

I have problem rendering page based on array of templates stored in redux. I'm unable to provide the actual code as it is too complex to reproduce in sandbox, but I will try with simplified structure.
I have pinterest-style grid based on flex-grow and js calculations for each item based on its dimensions so I need to have all of this inside one container.
I have 3 groups of items in same div:
blank_item + templates.map + tailItems.map
<div className="grid">
{shouldRenderBlankItem && <BlankItem />}
{templates.map((template) => (
<Template
key={template.uuid}
template={template}
/>
))}
{shouldRenderTail &&
tailItems.map(item, i) => (
<TailItem
key={i}
item={item}
/>
))}
</div>
The problem is - sometimes after render I have EXTRA children left from previous render and React puts them in front of other elements within div.grid so the result I have will look like:
3-4 of EXTRA <Template/> + blank_item + templates.map + tailItems.map
As a key for Template I use template.uuid that is coming from backend and I know they're unique and react also doesn't show any warnings for duplicated keys - so I know I'm not getting any duplicated items from API what I thought might be an issue.
Redux is fine - I see correct number of templates in it e.g. 50, grid and react dev tools shows same 50 templates coming as a prop when I inspect parent component, but the actual DOM has e.g. 53 elements in the same moment.
How can I debug issue like this? I suppose something is wrong during reconciliation but I don't know where exactly to start debugging this.
I have React/ReactDOM 16.13.1
Ok so in my case the problem was broken backend api which might return same template twice - so uuid's that I use for keys were unique for each template but they are not really unique in terms of the page and DOM elements.
I faced this only in production build that is why I didn't have duplicated key warning (on dev build I have another DB with much less templates so I was unable to reproduce this).
So anyone facing similar issue: go check your keys are really unique within page, because what happens after new templates load comes:
React wants to remove old item
It searches corresponding DOM element for each key and finds item with key="XXX" and removes it from DOM
Their duplicated items stays in DOM as corresponding key was processed and React doesn't care about this particular key anymore
We load new templates and they get appended to the parent container
Voila! We have old items before newly loaded
What I did here - my key now is:
templates.map((template, i) => <Template key={template.uuid + i} />
So in this case I am safe even if backend returns duplicated items.
Of course we will fix backend as well. Thanks for reading and helping!
Just quick example how to search for items with same id in data:
var duplicates = new Set();
data.map(t => t.id).forEach((id, i, arr) => {if(arr.filter(item => item == id).length > 1){
duplicates.add(id);
}});
console.log("DUPLICATED IDs:", duplicates)

How to get value from a dropdown to a button?

I'm using react JS and I have a problem. I don't know how to get the value from my dropdown and put that value into a onclick button. I have read lots of topics but I haven't find anything really useful for a beginner like me.
I am using "scheduler" that helped me built my dropdown and some other stuffs.
So, my dropdown get data from a local file and looks like this:
{values.map(v => (
<option value={this.value}>{v.value}</option>
))}
console.log(ref)
And my button is like this:
<Button onClick={() => this.decrement()}>
Ajouetr la réservation
</Button>
The decrement method was only there to test if it was working, and it is.
Actually, what I want to do is quite simple: I have some values in my dropdown (from 1 to 7). And I have a state that says there is 30 places available. What I want is when I choose a specified item in my dropdown AND validate with my button and then my state to decrement with the specified number. Because right now it only decrement with 1.
I hope it's clear enough for someone to help me, because I spent 2 days on that problem and I don't know what to do.
Thank you :)
Next time, it's nice to provide an interactive example with your question. Here's a CodeSandbox I made that (I hope) illustrates your example (link). If you want to fiddle with the example, just click "Fork" in the top right corner.
Back to the solution:
I think what you're missing is storing the selected value in your state along with the 30 "places". What you want is to make your <select /> tag into a "controlled component". When someone interacts with the <select /> you want to change the internal state so that it matches the selected value. That way, when you call decrement() from your button, you can use the internal state's value rather than getting it from a ref (I think that's what you were trying to do).
Here's a link to the React doc that explains how to use forms, specifically the <select /> tag: (link).
Take care!
I would say that you can think about this in 2 different steps:
SET THE QUANTITY STATE
Set the state with the current dropdown value - For achieving this, you can just use the onChange method in your select:
<select name="quantity"
value={this.state.quantity}
onChange={this.onSelectQuantity}
>
In your constructor, you create a variable quantity inside your state
Create a function called onSelectQuantity where you will set the quantity state with setState.
Do not forget to bind the function onSelectQuantity on the constructor.
With this, every time that you change the value on select, your state would capture its value. You can log it from the function if you want to test if it works.
DECREMENT FROM THE BUTTON
After this, you can just decrease the value of the state again from decrement function
<Button onClick={this.decrement}>
Ajouetr la réservation
</Button>
You will have a function...
decrement() {
const newQuantity = this.state.quantity - 1;
this.setState({
quantity: newQuantity
})
}
Hope it helps!

React - Select multiple checkboxes holding Shift key

I have a list of checkboxes in my React App. When I hold Shift key and click one - the others between current and the nearest checked one should become selected.
For now I'm tring to do somethimg like this:
<input onChange={(e)=>this.handleCheckbox(e)} value={id} checked={this.state.selected.IndexOf(id) > -1} type="checkbox" />
handleCheckbox(e){
if(e.shiftKey){
console.log("shiftKey is hold")
}
//here goes some logic to save checkboxes in the state
}
But the condition if(e.shiftKey) is never executed. What am I doing wrong?
For future visitors:
To check if the Shift key is pressed, check the e.nativeEvent.shiftKey in the click event.
You still have to implement the logic for actually checking the boxes. If you need help with that, let me know.
Hope this helps.
onChange is trigged after you let the key up. You should use the onKeyDown event.

New Map Object is hidden

I am mapping of array of object which multiplies my component, its working properly but the problem is when I add another object to it somehow its hidden not sure why
{EditMultiObject.map((object, key) => (
<SubFormEditCom
key={key}
identifyNumber={key}
onEditBasicChange={onEditBasicChange}
onEditCalendarChange={onEditCalendarChange}
onEditChangeUrl={onEditChangeUrl}
lastObject={EditMultiObject.length === key + 1 ? true : false}
onEditAddNewObject={onEditAddNewObject}
/>
))}
You will noticed the first element is the initial object I set the second is the one I created when I click a add button. The style on the second div is missing(the newly added one) an inline style, note that I didnt even put an inline style in my code I assume it was added by react
I think I know now whats the solution for this I think its because of the third party library

Resources