Render an array of Objects in ReactJs - javascript

I am trying to go through object properties (Name for this example) and list them within easy loop in function. I have found some pretty awkward way of doing this but it doesn't seem right.
Here is what i got:
const ItemsToSell = [{"Name":"Cup","Price":"99.99"},{"Name":"IPhone","Price":"99.99"},{
"Name":"Pen","Price":"99.99"}]
function ListItem(props) {
return <li>{props.value}</li>;
}
function NumberList(props) {
const a = props.numbers;
return (
<ul>
{a.map((number) =>
<ListItem value={ItemsToSell[number].Name} />
)}
</ul>
);
}
const numbers = [0,1, 2];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Is there a better way to do this?
I simply need a loop to go through array of objects, list needed properties and create one of many html nodes.

You can simply map over ItemsToSell array
const ItemsToSell = [{"Name":"Cup","Price":"99.99"},{"Name":"IPhone","Price":"99.99"},{
"Name":"Pen","Price":"99.99"}]
function ListItem(props) {
return <li>{props.value}</li>;
}
function NumberList(props) {
return (
<ul>
{ItemsToSell.map((obj, index) =>
<ListItem key={index} value={obj.Name} />
)}
</ul>
);
}
ReactDOM.render(
<NumberList />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Why don't you iterate over ItemsToSell array? You don't have to add yet another one.
Note: Include key property while looping the elements, else you will receive an error.
const ItemsToSell = [{"Name":"Cup","Price":"99.99"},{"Name":"IPhone","Price":"99.99"},{
"Name":"Pen","Price":"99.99"}]
function ListItem(props) {
return <li>{props.value}</li>;
}
function NumberList(props) {
return (
<ul>
{ItemsToSell.map((elem, index) =>
<ListItem value={elem.Name} key={index} />
)}
</ul>
);
}
ReactDOM.render(
<NumberList />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Related

Short circuiting not working in react render div

I want to start multiple components when a variable is true and I am using as follow:
return (
<div className="report">
{conditionalVariable &&
<ComponentA/> &&
<ComponentB/>
}
</div>
)
However, when the variable is true, only component A is getting up but not component B.What is wrong with this ?
I'm surprised you're getting any output. Those conditional components once you've worked out the logic, need to have a parent - either with a fragment, or a div, or something.
You would have seen something similar to this error:
SyntaxError: Inline Babel script: Adjacent JSX elements must be wrapped in an enclosing tag
const { Fragment, useState } = React;
function Example() {
const [ conditional, setConditional ] = useState(false);
function handleClick() {
setConditional(!conditional);
}
return (
<div>
{conditional && (
<Fragment>
<Test text="Bob" />
<Test text="Sue" />
</Fragment>
)}
<button onClick={handleClick}>
Click me
</button>
</div>
);
}
function Test({ text }) {
return <p>{text}</p>;
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Your curly braces are set rather strange. Try it like this:
return (
<div className="report">
{conditionalVariable &&
<>
<ComponentA />
<ComponentB />
</>
}
</div>
)
This solution uses the short syntax of React.Fragment to group the two components you want to display under the same condition.

How to get react props inside a map() function

Suppose I have a react function with props active.
// About Page
export default function About() {
return <Menu active="about" />;
}
// Menu Component
function Menu(props) {
const items = ["home", "about", "services", "contact"];
return (
<nav>
{items.map((item, index) => {
console.log(props);
return <li className={`${props.active === item && "active"}`}> {item} </li>;
})}
</nav>
);
}
How do I get the props.active inside the map() function? it's returning undefined right now.
Converted to snippet, Seems props is getting correctly.
(not related, but minor fix, if you use && in class name generation, for the falsy condition classname will be "false")
function About() {
return <Menu active="about" />;
}
function Menu(props) {
const items = ["home", "about", "services", "contact"];
return (
<nav>
{items.map((item, index) => {
console.log(props);
return (
<li className={`${props.active === item ? "active" : "inactive"}`}> {item} </li>
);
})}
</nav>
);
}
ReactDOM.render(<About />, document.getElementById('app'))
.active {
color: red
}
.inactive {
color: grey
}
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="app"> </div>
The above sample code in question works flawlessly.
In my project, I was actually modifying the wrong page to provide props, thus got {}
So, I'm writing this answer so that other people won't spend time on it.

React render inside class tag instead id

In my application, I have a requirement to render same data into multiple places via react.
So instead of rendering that via id (via below code), i want to use class tag.
ReactDOM.render(<App />, document.getElementById('app')); // Working
ReactDOM.render(<App />, $('.app')); // Not working.
My html is like below...
<div class="app" id="app"><div>
<div class="app"><div>
<div class="app"><div>
Update: below is my jsx file.
class PList extends React.Component {
static defaultProps = {
results: []
}
constructor(props) {
super(props);
this.state = {
results: this.props.results
};
}
render() {
return (
<ul>
{
this.state.results.map((item, i) => {
return <li>{item.Name}</li>
})
}
</ul>
);
}
}
var PRender = ReactDOM.render(<PList />, $('.app'));
function Professionals(data) {
PRender.setState({
results: data.Results
});
}
$('.app') - this is just an array, and ReactDOM.render requires single element as second parameter.
You can try as following if you need to render multiple App.
function App({index}) {
return `<div>App - ${index}</div>`;
}
document.querySelectorAll('.app').forEach((app, index) => ReactDOM.render(<App index={index + 1} />, app));
<html>
<div id="app">No ID assigned to App</div>
<div class="app"></div>
<div class="app"></div>
<div class="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</html>
Here's the answer for your edition.
https://codesandbox.io/s/hopeful-payne-1tloe?fontsize=14
Same as #Alona's answer. I tried to use jQuery -> $('.app') which described on question.
function App({index}) {
return `<div>App - ${index}</div>`;
}
$.each($('.app'), (index, app) => ReactDOM.render(<App index={index + 1} />, app))
<html>
<div class="app" id="app"></div>
<div class="app"></div>
<div class="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</html>

lodash map get index key got unexpected token

import { map } from 'lodash';
render(){
return(
{map(new_applicants, (obj,index) =>
<div key={index}>{index}</div>
)}
)
}
What's wrong with this code? obj is the single array of object been iterate and index is the key. I'm using lodash. The error look like this in console.
{map(new_applicants, (obj,index) =>
| ^
The problem is that the {...} syntax is being taken for an object initializer; you're doing this outside of JSX. That syntax is only valid within a JSX section, e.g.
<div>{map(...)}</div>
Also, render has to return a component (or null), it can't return an array. So perhaps:
return(
<div>
{map(new_applicants, (obj,index) =>
<div key={index}>{index}</div>
)}
</div>
)
Example:
const map = _.map;
class Foo extends React.Component {
render() {
const new_applicants = [1, 2, 3];
return(
<div>
{map(new_applicants, (obj,index) =>
<div key={index}>{index}</div>
)}
</div>
)
}
}
ReactDOM.render(
<Foo />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
Write it like this, {} it required when you are running the js code inside html element:
render(){
return(
<div>
{
map(new_applicants, (obj,index) =>
<div key={index}>{index}</div>
)
}
</div>
)
}

React: Access element's text

My component is used inside other render() like
return (<MyElem>Some text here</MyElem>)
How can I access the "Some text here" string inside my component's class?
You use the children property, which contains the children of your element (which might be text or an array of children [I think it's always an array when it's not text], see the link for the gory details). E.g.:
const Foo = props => {
console.log(props.children);
return (
<div>{props.children}</div>
);
};
ReactDOM.render(
<Foo>Hi There</Foo>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
That uses a stateless functional component (SFC), but it's the same for Component subclasses:
class Foo extends React.Component {
render() {
console.log(this.props.children);
return (
<div>{this.props.children}</div>
);
}
};
ReactDOM.render(
<Foo>Hi There</Foo>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Here's an example of the fact that children isn't just for text:
class Foo extends React.Component {
render() {
console.log(this.props.children);
return (
<div>{this.props.children}</div>
);
}
};
ReactDOM.render(
<Foo>
<div>Hi there</div>
<Foo><span>nested Foo > Foo > span</span></Foo>
</Foo>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Add a ref to To MyElem:
<MyElem ref="elem">My text here<MyElem>
Then you can refer to your element elsewhere with:
this.refs.elem

Categories