This article is in the reading of the official react tutorial after the finishing, instance link.
Getting Started with react
First get the latest version of React.js (v0.12.2) from the official, or download the official starter Kit and introduce them in our HTML:
<head>
<meta charset = "UTF-8">
<title> React Test Page </ title>
<script src = "../ build / react.js"> </ script>
<script src = "../ build / JSXTransformer.js"> </ script>
</ head>
JSX syntax
We can find in the code of the React component that the xml tag seems to be written directly into javascript:
React.render (
<CommentBox />,
document.getElementById (‘content‘)
);
This writing method is called JSX and is an optional feature of React. Writing XML tags directly in JavaScript looks more intuitive than calling JavaScript methods. To use this function normally, you need to introduce the JSXTransformer.js file into your page, or install react-tools using npm, and compile the source files containing JSX syntax into regular javascript files. The latter is recommended because after use This allows the page to use the compiled javascript file directly without the need for JSX compilation when the page is loaded.
HTML-like tags in JSX are not real HTML elements or HTML strings, but are instantiated React components. For more on JSX syntax, see this article.
Create component
React can create modular and composable components for us. For the comment area we need to do, our component structure is as follows:
-CommentBox
-CommentList
-Comment
-CommentForm
React.createClass () can be a React element, we can define our CommentBox like this, and the React.render () method allows us to render the React element as a DOM component in the specified container:
<body>
<div id = "content"> </ div>
<script type = "text / jsx">
var CommentBox = React.createClass ({
render: function () {
return (
<div className = "contentBox">
<h1> Comments </ h1>
<CommentList />
<CommentForm />
</ div>
);
}
});
React.render (
<CommentBox />,
document.getElementById (‘content‘)
);
</ script>
</ body>
From this example, we can also see that a component can contain subcomponents, and components can be combined (Composing), and present a tree structure. It can also be said that the CommentBox in the render method represents the root element of the component tree. Then let's create two subcomponents, CommentList and CommentForm.
The first is the CommentList component. This component is used to present the comment list. According to the component structure tree we designed at the beginning, this component should contain many Comment subcomponents. Then, suppose we have obtained the comment data:
var comments = [
{author: "Pete Hunt", text: "This is one comment"},
{author: "Jordan Walke", text: "This is * another * comment"}
];
We need to pass data to the CommentList component in order for it to render, so how do we pass it? We can access the properties on the component label through this.props. For example, we make the following changes in the code of the CommentBox component:
<CommentList data = comments />
So in the CommentList component, we can get our comment data by accessing this.props.data.
var CommentList = React.createClass ({
render: function () {
var commentNodes = this.props.data.map (function (comment) {
return (
<Comment author = {comment.author}>
{comment.text}
</ Comment>
);
});
return (
<div className = "commentList">
{commentNodes}
</ div>
);
}
});
Next write the Comment component. This component is used to render a single comment. We hope it can support the markdown syntax. So we introduce the showdown library. After introducing it in HTML, we can call it to make our comments support the markdown syntax. Here we need this.props.children property, which returns all child elements in the component tag.
var converter = new Showdown.converter ();
var Comment = React.createClass ({
render: function () {
return (
<div className = "comment">
<h2 className = "commentAuthor">
{this.props.author}
</ h2>
{converter.makeHtml (this.props.children.toString ())}
</ div>
);
}
});
Let's look at the effect now:
We found that the html tag was directly rendered after parsing, because React is XSS-protected by default, and all the rendered content is escaped, but in the current scene, we do n’t need its escape (if you cancel React's default XSS protection, then we need to rely on the library we introduced to have XSS protection or we handle it manually), then we can:
var converter = new Showdown.converter ();
var Comment = React.createClass ({
render: function () {
// access child elements of this element via this.props.children
var rawHtml = converter.makeHtml (this.props.children.toString ());
return (
// access element properties via this.props
// do not escape, insert straight HTML
<div className = "comment">
<h2 className = "commentAuthor"> {this.props.author} </ h2>
<span dangerouslySetInnerHTML = {{__ html: rawHtml}} />
</ div>
);
}
});
OK, our CommentList is complete, we need to add a CommentForm component so we can submit comments:
var CommentForm = React.createClass ({
handleSubmit: function (e) {
e.preventDefault ();
var author = this.refs.author.getDOMNode (). value.trim ();
var text = this.refs.text.getDOMNode (). value.trim ();
if (! text ||! author) return;
// TODO modify commentList
// Get the native DOM element
this.refs.author.getDOMNode (). value = ‘‘;
this.refs.text.getDOMNode (). value = ‘‘;
},
render: function () {
return (
// Add a submit event handler to the element
// Use ref to name the child components and reference them in this.refs
<form className = "commentForm" onSubmit = {this.handleSubmit}>
<input type = "text" placeholder = "Your name" ref = "author" />
<input type = "text" placeholder = "Say something ..." ref = "text" />
<input type = "submit" value = "Post" />
</ form>
);
}
});
From the above code, we can find that we can add event handlers to our components. For example, here we need to use the submit event of the form, so we can directly add the onSubmit attribute on the label. It should be noted that the event attribute needs to meet the camelcase naming rules, that is, if you want to add a click event, you must add onClick, and so on. Another point is that we need to get the contents of the two text boxes. The method used here is to add the ref attribute on the input tag, so that the input can be considered as a sub-component of it, and then you can access this.refs to After accessing this subcomponent, you can get the native DOM object for corresponding operations by calling the getDOMNode method.
We found that up to now, our page is static, but we hope that we can see our comments in the comments list immediately after successfully submitting the comments, and we can get the latest comments at regular intervals, which means that we Hope our CommentBox can change state dynamically.
First, let the CommentBox component make AJAX requests (here I use setTimeout to simulate the delay in obtaining data), get the comment data from the server and update the CommentList. React components have a private this.state property to store the variable state data of the component, but at the beginning we need an initial state. The initial state can be set by the component's getInitialState
Method, whose return value is the initial state value. At this time, we are not directly obtaining data from the attributes of the tag, we need to access this.state to obtain (this state attribute will return undefined if accessed directly with javascript, but it can be used like this.state.data in JSX) :
var CommentBox = React.createClass ({
getInitialState: function () {
return {data: []};
},
render: function () {
return (
<div className = "commentBox">
<h1> Comments </ h1>
<CommentList data = {this.state.data} />
<CommentForm />
</ div>
);
}
});
Next we need to get the comment data. We can implement it in the component's componentDidMount method. This method will be called once after the component is rendered on the page. We will update the state of the component after we get the data in this method. To update the state of a component, you need to call the component's this.setState method, so we write:
var CommentBox = React.createClass ({
// Executed only once in the component's life cycle, used to set the initial state
getInitialState: function () {
return {data: []};
},
loadCommentsFromServer: function () {
var self = this;
setTimeout (function () {
// dynamically update state
self.setState ((data: comments));
}, 2000);
},
// Called automatically when the component render is complete
componentDidMount: function () {
this.loadCommentsFromServer ();
setInterval (this.loadCommentsFromServer, this.props.pollInterval);
},
render: function () {
return (
<div className = "commentBox">
<h1> Comments </ h1>
<CommentList data = {this.state.data} />
<CommentForm />
</ div>
);
}
});
Now that we can update the data in the comment list, then the same comments that we successfully submitted in CommentForm can also be presented in CommentList. It should be noted here that the initial state we set now is the CommentBox component. The modification status is also the status of the modified CommentBox. If you want to change the status of the CommentBox in the CommentForm, you need to pass a method to the subcomponent CommentForm in the CommentBox component through the tag property, so that the handleSubmit in the CommentForm component can call this method ( (That is, the position of TODO above), so our code is like this:
var CommentBox = React.createClass ({
// Executed only once in the component's life cycle, used to set the initial state
getInitialState: function () {
return {data: []};
},
onCommentSubmit: function (comment) {
// simulate submitting data
comments.push (comment);
var self = this;
setTimeout (function () {
// dynamically update state
self.setState ((data: comments));
}, 500);
},
loadCommentsFromServer: function () {
var self = this;
setTimeout (function () {
// dynamically update state
self.setState ((data: data));
}, 2000);
},
// Called automatically when the component render is complete
componentDidMount: function () {
this.loadCommentsFromServer ();
setInterval (this.loadCommentsFromServer, this.props.pollInterval);
},
render: function () {
return (
// Not a real DOM element, but a React div component, with XSS protection by default
<div className = "commentBox">
<h1> Comments </ h1>
<CommentList data = {this.state.data} />
<CommentForm onCommentSubmit = {this.onCommentSubmit} />
</ div>
);
}
});
var CommentForm = React.createClass ({
handleSubmit: function (e) {
e.preventDefault ();
// e.returnValue = false;
var author = this.refs.author.getDOMNode (). value.trim ();
var text = this.refs.text.getDOMNode (). value.trim ();
if (! text ||! author) return;
this.props.onCommentSubmit ({author: author, text: text});
// Get the native DOM element
this.refs.author.getDOMNode (). value = ‘‘;
this.refs.text.getDOMNode (). value = ‘‘;
},
render: function () {
return (
// Add a submit event handler to the element
// Use ref to name the child components and reference them in this.refs
<form className = "commentForm" onSubmit = {this.handleSubmit}>
<input type = "text" placeholder = "Your name" ref = "author" />
<input type = "text" placeholder = "Say something ..." ref = "text" />
<input type = "submit" value = "Post" />
</ form>
);
}
});
At this point, our CommentBox component is complete, and the instance is linked.
Using React to write a comment area component (A preliminary exploration of React)