How to render array of objects in reactjs 1.0 with jsx? - reactjs

I have the following:
var repos = [{"keya":"vala","keyb":"valb"},{"keya":"vala","keyb":"valb"},{"keya":"vala","keyb":"valb"}]
In my react component code:
var React = require('react');
var Repos = React.createClass({
propTypes: {
username: React.PropTypes.string.isRequired,
repos: React.PropTypes.array.isRequired
},
render: function() {
return (
<div> REPOS<br />
Username: {this.props.username} <br />
Repos: {this.props.repos}
</div>
)
}
});
module.exports = Repos;
I see that:
{this.props.repos} returns the above, but I am getting an error:
Uncaught Error: Invariant Violation: Objects are not valid as a React child... check the render method.
How do I get around this? Is there a way to just output everything without iterating/looping through each one? I know I can do so in AngularJS, but I don't get why react is giving me a hard time.
I am using the newest version of react; I don't think this was a problem with 0.13.

Stringify it:
{JSON.stringify(this.props.repos)}

That depends on how you want to display the values in your HTML.
You could do something like
render: function() {
return (
<div> REPOS<br />
Username: {this.props.username} <br />
Repos:
{this.props.repos.map(function(repo){
return <div><span>{repo.keya}</span></div>;
}}
</div>
)
}
In general, you want to iterate over the array of values and return a HTML representation of it. That is why you are getting the error you mentioned, React doesn't provide a default HTML representation of an object so there is no way it will know how to display your array.
If you just want to display it as a text then the stringify method on the other answer is the way to go. But if you are expecting a pretty formatted output you will have to iterate over the array.

Related

Get refs via function call

I'm trying to replicate the React code from this official guide:
render: function() {
return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
this._input.focus();
},
Basically, I'm using ES5 and tried this:
componentDidMount: function() {
this.searchBox.focus();
},
render: function() {
return (
<input type="text" ref={function(c) {this.searchBox = c}} />
);
}
But I got an error saying:
Uncaught TypeError: Cannot read property 'focus' of undefined
Isn't the code above supposed to be the same like the ES6 version? I don't get it why it's not working. In case you're interested in the full code, here it is: https://jsfiddle.net/xpd85ehx/
ES5 and ES6 arrow notations use a different this.
Specifically, using the arrow notation, this is lexically bound to the surrounding function (so it refers to the class).
Using ES5 you will need to bind this to your function.
The es6 version uses arrow functions, which auto-binds the function to the existing scope. so for example,
function(c) {this.searchBox = c}
is not bound to the instance of the component, while
c => this.searchBox = c
is. In the first example, its hard to know what this is, but in the second, we can be pretty sure that this is a reference to our component`. If you want to make your solution work in es5, you need to manually bind, like this
render: function() {
return (
<input type="text" ref={(function(c) {this.searchBox = c}).bind(this)} />
);
}

React state - what I am doing wrong?

I am trying to learn reactjs and building small app that takes in names and then shows the names..
I have an input form, and I am able to get data from input form after clicking submit into my state object called names.
however I am stuck on passing the state from the parent to another component that is inside of my ShowNames component:
So, in App, I am doing this render:
render : function() {
return (
<div>
<InputName addToState={this.addToState}/>
<ShowName renderName={this.renderName}/>
</div>
)
}
});
Then ShowName component has following:
var ShowName = React.createClass({
render : function() {
return (
<ListOfNames renderName={this.props.renderName}/>
)
}
});
So I made
var ListOfNames = React.createClass({
render : function() {
return (
<ul renderName={this.props.renderName}>
{Object.keys(this.state.names).map(this.renderName)}
</ul>
)
}
});
But the issue is it says Cannot read property 'names' of null. Can someone help?
You need to initialise the state otherwise the state will be null.
React.createClass({
getInitialState: function() {
return { names: [] };
},
// all the rest here
}
EDIT
after seeing the code I noticed a couple of errors, the updated code is now here: http://jsbin.com/sewoxu/edit?js,output
So what the main error was that the render function of ShowName was using the state to get the names, but the names where passed via property:
<ShowName renderName={this.renderName} names={this.state.names}/>
so in this case to access the names attribute you need to do:
this.props.names
Also in the example I have moved the renderName function inside the ShowName component.
Hope this helps :)

Properties undefined on getInitialState

React noob here, trying to set an initial value for my checkbox control. I set the property and am trying to set the state to the property value using the getInitialState. Problem is, the props seem to be undefined in the getInitialState. I've simplified and created a jsbin to show the issue.https://jsbin.com/cujeveh/edit?html,js,console,output
var testcontrol = React.createClass({
getInitialState: function () {
return { testval: this.props.testval };
},
render: function() {
return (
<input type="checkbox" checked={this.state.testval?"checked":""}}/>
);
}
});
React.render(
<Container lblOn="yup" lblOff="nope"
buttonText="saveit" testval="1" />, document.body);
Also within the jsbin, tried the componentDidMount method with the same result. If I update the getInitialState to replace the prop with a hardcoded value, everything works fine. I did read the React docs here and did see the antipattern statement but am only trying to set the initial state which I understood as okay.
In your example, you're setting testval prop on the <Container> component, but not on the <Chkbox1> component, which is the component that is checking for it. Probably a minor oversight. You just need to change:
<Chkbox1 ref="box1" lblOn={this.props.lblOn}
lblOff={this.props.lblOff} />
to
<Chkbox1 ref="box1" lblOn={this.props.lblOn}
lblOff={this.props.lblOff} testval={this.props.testval}/>

ReactJS Read Json from url real time

I am looking into ReactJS. I've created database and added a table with some simple data.
Next I created a php file that will display the data in json format like this:
[{"ID":"1","Name":"name","Color":"green"}]
Next I've created a reactjs skeleton page and I'm trying to get it to read and display the json data but cannot find a simple example anywhere.
How can I get reactjs to read json from a url?
I created a fiddle which is a simple getting started and will give you an idea how to proceed.
Also, I think you will find this example from React Docs about loading data from ajax helpful. Code from there is as follows:
var UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
$.get(this.props.source, function(result) {
var lastGist = result[0];
if (this.isMounted()) {
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}
}.bind(this));
},
render: function() {
return (
<div>
{this.state.username}'s last gist is
<a href={this.state.lastGistUrl}>here</a>.
</div>
);
}
});
React.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
mountNode
);

How to use NPM installed react component in JSX?

I'm trying to use a 3rd party react component (react-slick) within my JSX and running into a problem. I'm attempting to use it very similarly to within this example by the app creator (example1.jsx snippet below).
Whenever I do this I get 2 warnings and an error:
Warning: This JSX uses a plain function. Only React components are valid in React's JSX transform.
Warning: Something is calling a React component directly. Use a factory or JSX instead. See: http://fb.me/react-legacyfactory
Uncaught TypeError: Cannot read property '__reactAutoBindMap' of null
I have also tried something similar as example2.jsx, which was a solution found in another Stack Overflow question. However, while no warnings, or errors were thrown, in this case the code did not render at all.
I have tried various methods of using React.createFactory (which shouldn't be used in JSX to begin with), and other finagling but with no results.
This is probably a stupid question but how the hell do I use NPM installed components in my JSX?
example1.jsx:
var React = require('react');
var Slider = require('react-slick');
var SingleItem = React.createClass({
render: function () {
var settings = {
dots: true,
}
return (
<div>
<h3> Image slider with one item at a time</h3>
<Slider dots={true}>
<div><img src="/img/autumn.jpg" alt=""/></div>
<div><img src="/img/sun.jpg" alt=""/></div>
</Slider>
</div>
);
}
});
var App = React.createClass({
render: function () {
return (
<div className='container'>
<SingleItem />
</div>
);
}
});
example2.jsx:
var App = React.createClass({
render: function () {
return (
<div className='container'>
{SingleItem}
</div>
);
}
});
It looks like you aren't actually referencing the slider component. You may find that your solution looks more like
var Slick = require('react-slick');
var Slider = Slick.Slider
Use the debugger to check what object you are actually being given by the require. It is also possible that you need to require a component by directly referencing one of the libraries file e.g.
var Slider = require('./slider.jsx');
Take a look at the lib or dist directory also, you can see the module.exports value for your require.
Use this to include Slick Slider component:
var Slider = React.createFactory(require('react-slick'));

Resources