setState an array of JSX elements? - reactjs

In my function component, I have an array of <div> I have created using the response of an axios call.
I want to render those divs in the return() function. It's important they stay as <div>s.
This attempt does not seem to work. I get an error about the array not being an appropriate child item of React.
const [firstNames, setFirstNames] = setState([])
....
let firstNamesArray = JSON.parse(response.data.first_names)
let newArr = []
firstNamesArray.forEach(element => newArr.push(<div>{element}</div>));
setFirstNames(newArr)
....
return (
{firstNames}
}
Is there a way to render an array of s or other JSX elements in one variable like in the example above?

While it'd be technically possible to return just the array of the JSX elements:
return firstNames;
State should not be composed of JSX elements. Instead, set the first_names array (of strings?) into state, then map the state to <div>s only when rendering:
setFirstNames(JSON.parse(response.data.first_names));
// choose some appropriate key here...
return firstNames.map((name, i) => <div key={i}>{name}</div>);

const firstNamesArray = JSON.parse(response.data.first_names)
return firstNamesArray.map((element, index) => (<div key={index}>{element}</div>))

Related

Removing an element in an array and then using map to make it dynamic React

I want to remove an element from the array arradd. Currently, I am able to use the id which is in incremented order and remove the element with the help of splice. However, this method is not dynamic since it does not return the map immideately. How do I make this dynamic?
const handleremove = (e) => {
arradd.splice(e.target.id, 1);
}
return(
{arradd.map((a, idx) => {
return <div key={a}>
<HoriContainer><Texty>{a}</Texty><img id={idx} idx={idx++} onClick={handleremove}src=
{cross}></img></HoriContainer>
</div>

Why can't I manipulate the DOM directly with React refs in my project? [duplicate]

This question already has answers here:
How can I use multiple refs for an array of elements with hooks?
(17 answers)
Closed 1 year ago.
Since my pathfinding project has too many cells for me to animate it by changing state I was told to use ref. I went with the forward ref approach, which I assume works becase in devtools each cell appears with the forwardRef tag.
Even when I try to console.log each ref it points me to the correct cell in the grid. The problem is when I try to mutate a property like className/bgColor, program crashes and gives me a TypeError: Cannot add property className, object is not extensible.
const node = (props, ref) => {
return (
<div ref={ref}>
</div >
)
}
const Node = React.forwardRef(node);
export default Node
function Grid() {
// How I created the refs
const refCollection = useRef(matrix.map(rows => rows.map(nodes => React.createRef())));
let grid = matrix.map((rows, i) => rows.map((_, j) => <Node
ref={refCollection.current[i][j]}
></Node>))
function createMazeAndAnimate() {
const orderCarved = generateMaze(rows, cols, setWall, setStartNode,
setGoalNode, setTraversed, setCarvedOrder);
orderCarved.forEach(([y, x], i) => {
setTimeout(() => {
refCollection.current[y][x].className = 'traversed'; //PROGRAM CRASHES HERE
console.log(refCollection.current[y][x]); // IF I JUST LOG THIS LINE I CAN
// SEE EACH CELL REFERENCED
// CORRECTLY
}, i * 20);
})
}
return (
<>
<Toolbar
generateMaze={createMazeAndAnimate}
/>
<div
className='grid'
>
{grid.map((row, i) => <div key={i} className='board-row'>{row}</div>)}
</div>
</>
)
}
Thank You!
You're trying to modify refs directly. You don't mutate a ref object itself, you mutate whatever's in ref.current. So you want refCollection.current[y][x].current.
Putting a ref inside a ref is a code smell, as a ref itself is designed to be mutated, putting it inside something else you mutate seems extraneous. You might want to put your ref array in state instead.

how to render array in object in array? (react)

const checked = [{
food:['apple', 'banana']
drink:['wine', 'beer']
}];
render (
<>
{checked.map((value) => {
value.food.forEach((each) => (
<div>{each}</div>
)
)}
</>
)
I tried this way and noting is shown in browser..
what would be the best way to approach?
Need to Return Your data like below!!
import React from "react";
export default function App() {
let checked = [{
food:['apple', 'banana'],
drink:['wine', 'beer']
}];
return (
<div className="App">
{
checked.map((item) => {
return item.food.map((fruit)=>{
return <h1>{fruit}</h1>
})
})
}
</div>
);
}
Your code has multiple errors.
It should be render instead of rander
While defining object, multiple properties should be separated using a comma. So put comma after the food array.
forEach doesn't return any thing. It just iterates over an array. So, if you want to return something (in this case a div element), use map.
Also, you should use key for each div element otherwise react would give you a warning in the console. This is done so that while re-rendering, based on the keys, react would understand which component to re-render and which to skip. Otherwise all the div would be re-rendered which is a costly operation.
const checked = [
{
food: ["apple", "banana"],
drink: ["wine", "beer"]
}
]
return (
<>
{checked.map((value) => {
return value.food.map((each, index) => {
return <div key={index}>{each}</div>;
});
})}
</>
);
There is a couple of improvements that require to be implemented to make the list displayed.
First, the map method does not return anything.
Two solutions:
Remove the curly brackets checked.map((value) => value...
Add a return keyword: checked.map((value) => { return value...}
The other issue is that the second loop is iterated using the forEach method.
The difference between the two (forEach and map) from MDN:
The forEach() method executes a provided function once for each array
element.
MDN
The map() method creates a new array populated with the results of
calling a provided function on every element in the calling array.
MDN
Basically, it means that forEach does not return anything and that why you need to use map
checked.map((value) => {
return value.food.map((each) => (<div>{each}</div>))
})}
or
checked.map((value) =>
value.food.map((each) => (<div>{each}</div>))
)}
You are iterating over the checked array items using forEach which won't induce any results since the forEach method
executes a provided function once for each array element.
which won't result in a transformed array.
What you are looking for is the map method which
creates a new array populated with the results of calling a provided function on every element in the calling array.
hence returning your transformed items so that they can be rendered (transformed at compilation time to ReactElement using the JSX syntax).
Note that you need to use an HTML tag instead of a React.Fragment the empty tag <> syntax:
const checked = [{
food:['apple', 'banana'], // there is a missing comma here
drink:['wine', 'beer']
}];
render ( // render and not rander
<div> // div instead of empty tag
{checked.map((item) => item.food.map((each) => <div>{each}</div>))}
</div>
)
Can check this approach. if you want to print just food values, below code should work. If you want to print all the values (both food and drink), then uncomment the commented code below.
export default function App() {
const checked = [
{
food: ["apple", "banana"],
drink: ["wine", "beer"]
},
{
food: ["grapes", "oranges"],
drink: ["coke", "sprite"]
}
];
// to display values of all arrays.
// return (
// <>
// {checked.map((value) => {
// const keys = Object.keys(value);
// return keys.map((eachKey) => {
// return value[eachKey].map((individualValue) =>
// (
// <div>{individualValue}</div>
// )
// )
// });
// })
// }
// </>
// );
// To display just food values.
return (
<>
{checked.map((value) => {
return value.food.map((each) => <div>{each}</div>);
})}
</>
);
}

React display objects of an array

I have to display objects of an array in a react. I have done below code after searching on web. But it's not working. Can someone please help me where I am making mistake. Thanks in Advance!!
<div>
{items.map((value, index) => {
return (<div className="note" key = {index}>{value.title}</div>);
})}
</div>
The above implementation should work.
Unless you misspelled something.
Note: react does not display values if they are null.
Make sure value.title actually exits in the objects of the array.
Do the mapping outside of the render method, store the array in a variable and you can now display that variable inside the render method.
const list = items.map((value,index) => {
return (<div key={index}>{value.title}</div>)
})
render(){
<div>{list}</div>
}

React refs not being evaluated

I have a simple component in React, witch renders another component as follows.
_getResultsListComponent: function () {
var data = {
...blabla
};
return
<Popout
id='popout'
ref="searchResults"
closeResults={this._closeResults}
pointerAlign="center"
>
<this.props.resultsList data={data} />
</Popout>
},
render: function () {
return (
<div className='blabla'>
{this._getResultsListComponent()}
</div>
);
}
However, if i print 'this.refs' after mount ill get the exact string ive put into refs, for example:
ref="searchResults"
printing this.refs after mount gets me
searchResults
If i change the refs to
ref="{(compo) => {this.component = compo}}"
ill get when printing:
{(compo) => {this.component = compo}}
Like if the refs are not being evaluated.
Am i missing something ?
React no longer sets a "refs" object on the class but instead uses a callback so that you can assign a class property a unique name for the element. In this case this.component will contain the value of the compo prop passed to the callback.
ref accepts a callback function and you need to remove the quotes for it to be evaluated
ref={(compo) => {this.component = compo}}
You can later access the ref like this.component

Resources