React mapping not splitting array when returning - reactjs

I'm attempting to render errors when submitting a form using React (jsx files). In my form component, I render an error message as part of the component:
...
<ul>Error: {props.errors.map((err, idx) => <li key={idx}>{err}</li>)}</ul>
...
However, even though my props.errors is an array composed of two strings ["Title cannot be blank", "Body cannot be blank"], the resulting list is only composed of one item joining both of these errors together without a comma ("Title cannot be blankBody cannot be blank).
I've additionally tried joining the two together using Array.join(", "), but this also would not add the space in-between the errors. Does anyone have an idea of why several items are being returned/rendered as a single item in React?

It turns out that the error array is actually a nested array, even though the Chrome console only shows it as a singular array. To solve this, therefore, I had to call props.errors[0].map if the array has a length greater than 0, then map through it.

Related

How to create new line in react table column with lots of data

I am using react table. I am calling a method on API (.NET), which concatenates some fields and now I need to display this concatenated field in react table column.
From API I tried to put /n in the column so that it renders a new line on UI (inside react table). But no luck. Example: I need to display
This field is calculated by adding two numbers 10 and 20. Since the
result is greater than 15 you cannot perform this operation.
In the displayed text, what I want is "Since" should start in a new line in react table.
I tried to put {'\n'} before "Since" but it did not work. Any ideas how to achieve this?
The '\n' escape character does not work in HTML. You have to work with
other HTML solutions like using <br> or divs to get a multiline
implementation working.
You solve this quite easily. when getting the string append a special char like the comma (,) or some other char that you are sure would not be used in your original text.
Then get that string to a js variable in your react app.
let multiLineString = "This field is calculated by adding two numbers 10 and 20. , Since the result is greater than 15 you cannot perform this operation";
let lines = multiLineString.split(',')
let linesHTML = lines.map((line)=><div>{line}</div>);
now render this variable anywhere you want, you will get a multi line string implementation.
Of course the better approach would be to get a json array of values from the back end.

React Collapse transition doesn't animate when wrapped in a div with a dynamic key

This is really weird. It took me many hours to figure out how to fix this. But even with it fixed, I don't know why it breaks in one configuration but not the other.
The best way to explain this is with the StackBlitz live example: https://stackblitz.com/edit/react-collapse-transition-breaks-with-dynamic-key
The live example details the exact issue, but here's the synopsis:
It's a React app using Material UI.
I have a <List> that is populated with an array of <ListItem>s.
Those <ListItem>s are clickable. When you click them, it uses the <Collapse> transition to expose a sub-<List> of "subheaders". The subheader <List>s are also populated with an array of <ListItem>s.
Here's where it gets weird: I have a simple <div> that holds the "header" <ListItem>s and the <Collapse>-ible <List> of "subheaders".
Because these are part of an array, React complains if I don't add a "key" attribute to top-level element (the <div>).
If I add a dynamically-generated key value to that containing <div>, it somehow kills the transition animation on the <Collapse> element. The <Collapse> still opens-and-closes, but it doesn't animate over a set number of milliseconds. It just opens (immediately) or closes (immediately).
If I add a static key value to that same containing <div>, the animation works just fine.
Why does the dynamic-key approach break the animation??
TLDR: Do not dynamically-generate globally-unique keys for array elements in React.
OK, after repeated attempts at Googling, I think I finally understand what's going on.
When you add items to an array in React, a warning is thrown if you don't add a unique "key" to each element in the array. As long as you use something unique as the "key" value for each element, the warning goes away and, for the most part, React seems to manage the array elements just fine.
When I was starting React development (a few years ago), I thought, "I can solve this easily by using a random GUID-generating function to add unique keys to all my array elements. So I would frequently use code that looks like this:
let newArray = [];
someMasterArrayOfObjects.forEach(object => {
if (someConditionIsMet) {
// SEE HOW CLEVER I THOUGHT I WAS?? USING A RANDOMLY-GENERATED GUID QUIETS THE
// UNIQUE-KEY WARNINGS THAT ARE THROWN BY REACT
newArray.push(
<div key={createRandomGuid()}>
{object.title}
</div>
);
}
});
But I missed one key word from the ReactJS documentation (emphasis, mine):
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a STABLE identity:
They use the word "stable" a few times in the documentation, but it didn't really sink into my thick skull. Like most devs, my first concern was removing the warning that is thrown when array elements are missing a unique key. And using a randomly-generated GUID solved that problem.
But React uses those keys to figure out what should be re-rendered during state changes. If you randomly-generate a new, globally-unique key every time you build the elements in the array, then React will assume that all of these elements need to be completely rebuilt from scratch every time you set state.
At the very least, this is inefficient. You may not notice any performance effects in small arrays/apps, but there's no reason to artificially force a re-rendering of every array element every time that state is set for any reason. You may not notice any visual problem in your app, but it's poor practice.
At the worst, it will actually break some of your functionality. In my case, it was breaking the <Collapse> transition animation because the rendering engine couldn't compare the incremented "height" value between one state change and the next - because on every attempt to change that height, I was assigning a brand new, globally-unique identifier to the "key" value and React was seeing it as an entirely new, entirely different component.
Once I finally figured out what to Google, I also found this great JSFiddle:
http://jsfiddle.net/frosas/S4Dju/
Notice that the center row of inputs in his example are titled "Unique random keys". When you manually change the value of one of the those unique random keys, then you click on "Add item", it blows away the results of your changes, because it re-renders the input elements as brand-new elements with no ties to their previous state.

React Keys : Understanding the behaviour of keys if defaultValue is used in Input field

I was trying to understand the usage of keys in React and found this link https://coderwall.com/p/jdybeq/the-importance-of-component-keys-in-react-js where 3 scenarios are explained.
Using indexes for keys
Using of Random Unique Number for keys
Using of constant Unique Numbers for keys
<input key={item} id={item} defaultValue={item}/>
In the example, when I used value instead of defaultValue, I see different behaviour (Change in last DOM value not reflecting if new item is added).
Can any one explain the behaviour in three scenarios in the example.
You can find the code here
To explain you the three cases with respect to your input case
First: indexes for keys,
When using indexes for keys, the only problem is that if you re-order the data or day delete the data in between, a lot of elements needs to re-render as the key to component mismatch is happening and during reconcilation React is not able to compare elements correctly
Second: Using random number as keys
Using random number in render is worst possible idea for setting keys, as each time render is called, a new random key is generated and assigned to the component and hence the entire DOM elements will be reconciled and re-rendered. With input another issue is that each time you change a value, a re-render is triggered and since the elements are recognized differently because they have different keys, the input loses focus
Third: Using of constant Unique Numbers for keys
This is the best case scenario, as even though the elements are re-ordered or some elements are deleted from the middle of the array, the previously rendered item will always hold the same keys and hence during reconcilation only elements that changed will be re-rendered

Empty string[] element in JSP

I have a JSP that populates an int[] and string[] via Spring controller. When a string value for an index is "", the JSP renders all of the values from the string[].
Controller populates string[] ids & values.
form.setIds(ids);
form.setValues(values);
The JSP loops through and populates a table.
<c:forEach items="${form.ids}" varStatus="status" var="id">
<form:input path="values" value="${form.values[status.index]}" />
When string[]:values contains: {"a","b","","d"}, elements 0,1,3 show as expected: 0="a", 1="b", 3="d". Element 2 shows: "a,b,,d" for the output to the JSP for that line.
I've tried several ways to render, such as wrapping output in JSTL taglib, and changing to array lists instead of primitive string[].
I have a feeling I'm overlooking something :)
I think your bug lies elsewhere. ${form.values[status.index]} will indeed print nothing if the content of your array is really is an empty string.
This one took a while.
The issue was that using path="values" on the form input, when we hit a empty element it would show all of "values" instead of the intended blank value. The fix was to use path="values[${status.index}]" for the form input.
Also, in order to use an element, I had to switch my underlying form from using String[] objects to List objects. This was due to the form not having an initialized String[] value upon loading, whereas I could init as ArrayList without having to specify a specific length to the string array.

d3 .filter function stops while matching string values in two arrays when a 'no match' occurs

Intent:
Match strings from localStorage with strings in array from .csv and change style when there is a match.
All available words are in two different .csv files. In localStorage some of the words, either from file 1 or from file 2, are stored.
On page refresh either csv-list 1 or csv-list 2 is displayed, not both together.
The following code gets strings from localStorage:
retrieveMarks = window.localStorage.getItem("marked")
wup = JSON.parse(retrieveMarks);
console.log("hi" + wup)
and displays correctly in the console:
hicsalád,nő,bank,hal,kabát,baba,vasútállomás,étel,ügyvéd,banán,diák,gyermek,energia
I am now using this list in a filter, successfully matching against a second array d ( strings from .csv ); changing the style successfully and as intended:
console.log(d3.selectAll(".bubble-label-name").filter((d) -> textValue(d) in wup).style("border", "6px solid red"))
The problem:
Instance 1: the values (d) -> textValue(d) are loaded from First.csv file; everything works fine; all the matching strings have the desired effect
Instance 2:the values (d) -> textValue(d) are loaded from the Second.csv file, the style change does not occur anymore.
My interpretation:
The filter .filter((d) -> textValue(d) in sup) starts matching at the beginning of the localStorage array. When it does not find a string, progression stops. The filter does not evaluate the second word from localStorage etc..
Is this correct ? What code is needed to progress filtering when a no-match occurs, skipping to the next match ?
Solution:
Please see the solution here. Getting the value fro two different cvs was not really an issue, just a typo.
d3 localStorage.getItem() compare arrays .filter()

Resources