I am starting to get involved in ReactJS, I am trying to pass to my tag a JSON object so then I can show it in the UI but it keeps saying that element is not found. Any help on this? Or why the props object is not having the JSON object? Thanks in advance
var CommentBox = React.createClass({
render: function() {
return (
<div className="img-container">
<img src="{this.props.placementImage}" />
</div>
);
}
});
var MP = [
{
id: "MP1001",
placementImage: "https://www.aexp-static.com/intl/uk/rwd/images/UKHP_CM_promo_3.png",
dts: "forever",
dte: "forever",
status: "",
isDefault: false
}
];
ReactDOM.render(
<CommentBox mp={MP}/>,
document.getElementById('content')
);
A couple things:
You're passing an array as the mp prop, but then attempting to access it like an object.
You need to remove the quotes from the <img> src attribute:
You need to access the actual mp prop
For reference, I've created a JSBin example from your code that fixes these issues: http://jsbin.com/bohoqa/edit?html,js,output
var CommentBox = React.createClass({
render: function() {
return (
<div className="img-container">
<img src={this.props.mp.placementImage} />
</div>
);
}
});
var MP = [
{
id: "MP1001",
placementImage: "https://www.aexp-static.com/intl/uk/rwd/images/UKHP_CM_promo_3.png",
dts: "forever",
dte: "forever",
status: "",
isDefault: false
}
];
ReactDOM.render(
<CommentBox mp={MP[0]}/>,
document.getElementById('content')
);
change
<img src="{this.props.placementImage}" />
to
<img src={this.props.mp[index].placementImage} />
You have to pass them as objects {} not "{}"
edit: I did not notice it was an array
Related
I'm trying make an AJAX call to get server data into my React Components.
I'm unable to display it with React. I get this error:
Uncaught TypeError: Cannot read property 'map' of undefined
I've done research http://andrewhfarmer.com/react-ajax-best-practices/ and reactjs - Uncaught TypeError: Cannot read property 'map' of undefined ;however, I'm not sure how to map it to my react component.
Here is my code below:
var items;
$.get("http://localhost:3000/getProducts", function( data ) {
items = data;
this.state.items = data;
});
/*React Code Below */
var RepeatModule = React.createClass({
getInitialState: function() {
return { items: [] }
},
render: function() {
var listItems = this.props.items.map(function(item) {
return (
<div className='brick'>
<div>
<a target='_blank' href={item.productURL}><img src={item.imageURL}/></a>
<p className='itemName'>Short Sleeve Oxford Dress Shirt, White, Large</p>
<p className='storeName'>Nike Factory Store</p>
<img className='foundPicture' src='../images/rohit.png'/>
</div>
</div>
);
});
return (
<div>
{listItems}
</div>
);
}
});
ReactDOM.render(<RepeatModule items={items} />,
document.getElementById('clothing-content'));
My JSON array with item properties are valid:
Here is the array below:
[ { _id: 584d1e36a609b545b37611ac,
imageURL: 'http://ih1.redbubble.net/image.252113981.3904/ra,unisex_tshirt,x1350,fafafa:ca443f4786,front-c,30,60,940,730-bg,f8f8f8.u2.jpg',
productName: 'Drake',
productType: 'T-Shirts & Hoodies',
price: '$29.97',
productURL: 'http://www.redbubble.com/people/misfitapparel/works/22923904-drake?grid_pos=6&p=t-shirt',
__v: 0 } ]
Why is this error occurring? And how should it be implemented?
Javascript is asynchronous. Your get function callback does not block program flow, it executes at a later time. The rest of your code will continue to execute. You're sending an AJAX request asynchronously, then you're rendering a react component with an undefined variable. Then, at a later time, the get request will finish and your data will be populated, but this is long after rendering has completed.
The simplest solution here is to only render the component once your AJAX request has finished:
var RepeatModule = React.createClass({
render: function() {
var listItems = this.props.items.map(function(item) {
return (
<div className='brick'>
<div>
<a target='_blank' href={item.productURL}><img src={item.imageURL}/></a>
<p className='itemName'>Short Sleeve Oxford Dress Shirt, White, Large</p>
<p className='storeName'>Nike Factory Store</p>
<img className='foundPicture' src='../images/rohit.png'/>
</div>
</div>
);
});
return (
<div>
{listItems}
</div>
);
}
});
$.get("http://localhost:3000/getProducts", function( data ) {
ReactDOM.render(<RepeatModule items={data} />,
document.getElementById('clothing-content'));
});
A better solution, depending on your needs, is probably to do the AJAX request in a componentDidMount lifecycle method, and store the result in state instead of props.
var RepeatModule = React.createClass({
getInitialState: function() {
return { items: this.props.items || [] }
},
componentWillMount: function() {
console.log("componentWillMount()")
$.get("http://localhost:3000/getProducts", function( data ) {
this.setState({ items : data })
console.log(data,"data is here");
}.bind(this));
},
render: function() {
var listItems = this.state.items.map(function(item) {
return (
<ListItem item={item}/>
);
});
return (
<div>
{listItems}
</div>
);
}
});
/* make the items stateless */
var ListItem = function(props) {
return (
<div className='brick' key={props.item._id}>
<div>
<a target='_blank' href={props.item.productURL}><img src={props.item.imageURL}/></a>
<p className='itemName'>Short Sleeve Oxford Dress Shirt, White, Large</p>
<p className='storeName'>Nike Factory Store</p>
<img className='foundPicture' src='../images/rohit.png'/>
</div>
</div>
);
}
var data = []
ReactDOM.render(<RepeatModule items={data} />, document.getElementById('clothing-content'));
I had to bind the data and use componentWillMount.
I saw some questions speaking about similar issues but somehow I still do not manage to solve my issue so here I am asking for your kind help. I am pretty new to React and would like to send a function from a Parent to a child and then use it from the Child but somehow when I want to use it it says
Uncaught TypeError: Cannot read property 'props' of undefined"
Edited Code after first answers were helping:
var Menu = React.createClass({
links : [
{key : 1, name : "help", click : this.props.changePageHelp}
],
render : function() {
var menuItem = this.links.map(function(link){
return (
<li key={link.key} className="menu-help menu-link" onClick={link.click}>{link.name}</li>
)
});
return (
<ul>
{menuItem}
</ul>
)
}
});
var Admin = React.createClass ({
_changePageHelp : function() {
console.log('help');
},
render : function () {
return (
<div>
<div id="menu-admin"><Menu changePageHelp={this._changePageHelp.bind(this)} /></div>
</div>
)
}
});
ReactDOM.render(<Admin />, document.getElementById('admin'));
Pass a value from Menu function and recieve it in the changePageHelp function and it works.
var Menu = React.createClass({
render : function() {
return (
<div>
{this.props.changePageHelp('Hello')}
</div>
)
}
});
var Admin = React.createClass ({
_changePageHelp : function(help) {
return help;
},
render : function () {
return (
<div>
<div id="menu-admin"><Menu changePageHelp={this._changePageHelp.bind(this)} /></div>
</div>
)
}
});
ReactDOM.render(<Admin />, document.getElementById('admin'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="admin"></div>
For performance reasons, you should avoid using bind or arrow functions in JSX props. This is because a copy of the event handling function is created for every instance generated by the map() function. This is explained here: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
To avoid this you can pull the repeated section into its own component. Here is a demo: http://codepen.io/PiotrBerebecki/pen/EgvjmZ The console.log() call in your parent component receives now the name of the link. You could use it for example in React Router.
var Admin = React.createClass ({
_changePageHelp : function(name) {
console.log(name);
},
render : function () {
return (
<div>
<div id="menu-admin">
<Menu changePageHelp={this._changePageHelp} />
</div>
</div>
);
}
});
var Menu = React.createClass({
getDefaultProps: function() {
return {
links: [
{key: 1, name: 'help'},
{key: 2, name: 'about'},
{key: 3, name: 'contact'}
]
};
},
render: function() {
var menuItem = this.props.links.map((link) => {
return (
<MenuItem key={link.key}
name={link.name}
changePageHelp={this.props.changePageHelp}
className="menu-help menu-link" />
);
});
return (
<ul>
{menuItem}
</ul>
);
}
});
var MenuItem = React.createClass ({
handleClick: function() {
this.props.changePageHelp(this.props.name);
},
render : function () {
return (
<li onClick={this.handleClick}>
Click me to console log in Admin component <b>{this.props.name}</b>
</li>
);
}
});
ReactDOM.render(<Admin />, document.getElementById('admin'));
http://jsfiddle.net/adamchenwei/3rt0930z/20/
I just trying to create an example to learn how state works in a list.
What I intent to do is to allow a particular value that got repeated in a list, to change, in ALL items in the list, by using state. For example, in this case, I want to change all the list item's name to 'lalala' when I run changeName of onClick.
However I have this warning (issue at fiddle version 11, resolved at version 15)
Any help on resolving it to achieve purpose above?
Actual Code
var items = [
{ name: 'Believe In Allah', link: 'https://www.quran.com' },
{ name: 'Prayer', link: 'https://www.quran.com' },
{ name: 'Zakat', link: 'https://www.quran.com' },
{ name: 'Fasting', link: 'https://www.quran.com' },
{ name: 'Hajj', link: 'https://www.quran.com' },
];
var ItemModule = React.createClass({
getInitialState: function() {
return { newName: this.props.name }
},
changeName() {
console.log('changed name');
this.setState({ newName: 'lalala' });
},
render() {
//<!-- <a className='button' href={this.props.link}>{this.props.name}</a> -->
return (
<li onClick={this.changeName}>
{this.state.newName}
</li>
);
}
});
var RepeatModule = React.createClass({
getInitialState: function() {
return { items: [] }
},
render: function() {
var listItems = this.props.items.map(function(item) {
return (
<div>
<ItemModule
key={item.name}
name={item.name} />
</div>
);
});
return (
<div className='pure-menu'>
<h3>Islam Pillars</h3>
<ul>
{listItems}
</ul>
</div>
);
}
});
ReactDOM.render(<RepeatModule items={items} />,
document.getElementById('react-content'));
-UPDATE-
fiddle version 16
updated fidle, now there is issue with key, also, the onClick did not update the value for all the list item. Is there something wrong I did?
-UPDATE-
fiddle version 20
Now the only issue is change all the list item's name to 'lalala' when I run changeName of onClick.
remove the parenthesis from
onClick={this.changeName()},
so
onClick={this.changeName}
you want to call the function onClick, but you are calling it on render that way
I think you meant to do onClick={this.changeName}
In the way you have it you are calling the changeName function on render instead of on click.
My simple component:
var AddProductForm = React.createClass({
render: function(){
return(
<form >
<input type='text' placeholder='lablbalbalbal'/>
</form>
)
}
})
My second component that I want to 'render' the first component in some determined div via onClick:
var HeaderAction = React.createClass({
render: function(){
return(
<button type="button" onClick={this.handleClick} className="btn border-slate text-slate-800 btn-flat"><i className={this.props.icon + " position-left"}></i>{this.props.name}</button>
)
},
handleClick: function(){
var component = React.createElement(this.props.action.component);
ReactDOM.render( component, document.getElementById('content'));
}
})
When I click my 'HeaderAction' component, an error occurs:
Uncaught Invariant Violation: Invalid tag:
The console.log() from my 'component' :
Object {$$typeof: Symbol(react.element), type: "<AddProductForm/>", key: null, ref: null, props: Object…}
$$typeof: Symbol(react.element)
_owner: null
_self: null
_source: null
_store: Object
key: null
props: Object
ref: null
type: "<AddProductForm/>"
__proto__: Object
If in the render call I change 'component' for "<AddProductForm/>" it works fine, but using the createElement for instantiate the object before the render doesn't.
var AddProductForm = React.createClass({
render: function(){
return(
<form >
<input type='text' placeholder='lablbalbalbal'/>
</form>
)
}
})
var HeaderAction = React.createClass({
render: function(){
return(
<button type="button" onClick={this.handleClick}</button>
)
},
handleClick: function(){
var component = React.createElement(AddProductForm);
ReactDOM.render( component, document.getElementById('content'));
}
})
var mount = document.getElementById('container');
ReactDOM.render(React.createElement(HeaderAction), mount)
I do not have an answer for you, however this seems to work. I do not know what this.props.action.component is in your case. I have created a small fiddle. Maybe we can work this out. https://jsfiddle.net/walkerrsmith/htaca7fa/
I want to create something like below in ReactJS but i can't figure out how and I most definitly don't want to use DangerouslySetInnerHTML. It's just a stupid example but i hope it makes clear what i want. Thanks for helping me out!
var page = {
title: <ReactTitle title={this.props.page.name} />
name: "Me myself and I"
};
var ReactTitle = React.createClass({
render: function(){
return (
<h1>{this.props.title}
);
}
})
var NewPage = React.createClass({
render: function(){
return (
<div className="row">
{this.props.page.title}
<div className="page-header"><h1>{this.props.page.name}</h1></div>
</div>
);
}
})
React.render(
<NewPage page={page} />
);
You can use React.createElement, like so
var page = {
title: React.createElement(ReactTitle, {title: "My awesome Title"}),
name: "Me myself and I"
};
Example
But in my opinion better use ReactTitle inside NewPage, like so
<div className="row">
<ReactTitle title={this.props.page.title} />
<div className="page-header"><h1>{this.props.page.name}</h1></div>
</div>
Example
My solution, with thanks to #Alexander
//Example
var page1 = {
title: [
React.createElement("h1", "", "This is my page title");
React.createElement("div", {className:"page-header"}, "This is the header of page 1");
],
name: "Me myself and I"
};
//So page2, which is slidely different:
//Example
var page2 = {
title: [
React.createElement("h2", {className:"h2"}, "Title part",
React.createElement("span", {className:"silent"}, "Silent part of page title")
),
React.createElement("div", {className:"page-header"}, "This is the header of page 2");
],
name: "Me myself and I"
};