The following is the react Official document thinking Inreact article translation, the first translation of English articles, there must be a lot of incorrect places, but also hope to forgive.
Original address: https://facebook.github.io/react/docs/thinking-in-react.html
Beginning of the original
---------------------------------------------I'm a delimiter------------------------------------------
Thinking in React
by Pete Hunt
What is react? My view is that it is the first way to create large, fast Web applications with JavaScript. Fackbook and Instagram have done a good job of testing for us.
One of the most powerful parts of react is how you think when building your app. Next, I'll show you how to use react to build a product data sheet with search capabilities.
Start with a mockImagine that we already have the JSON data API and the designer-given site model. Our designer is obviously not as good as the model he gives:
The data returned by our JSON interface is this:
Step 1:break the UI into a component hierarchy (split UI into component layer)
The first thing you need to do is to draw boxes around the components and give them a name. If you have worked with a web designer, they may have already done the job and talk to them. of their
The name of the Photoshop layer should eventually be the name of your react component. But how do you know who should be a separate component? This is the way to do it: depending on whether you need to create a new method or object, you can decide whether it is a component. This is the principle of single responsibility, the principle is: a component in the ideal state to do only one thing. If you need to extend it later, then split it into sub-components.
If you often present the JSON data model to the user, you will find that if your model is built correctly, the layout of your UI (that is, your component structure) will not be problematic. Because both the UI and the data model depend on the same information structure, it is common to think that separating your UI into components is trivial. To separate the UI into components that represent a single-block data model.
You can see that there are five components in our simple application,
1.FilterableProductTable (Orange): Contains the whole of the application.
2.SearchBar (blue): User input received
3.ProductTable (green): Display and filter data based on user input
4.ProductCategoryRow (sky blue) area title
5.ProductRow (red): Show lines for each product
If you look at producttable, you will find that the table header (containing the ' Names ' and ' price ' tags) is not its own component. This is a preference and there is a lot of controversy about it. In this example, I put it in producttable because it is part of the rendering producttable data set. However, if the header becomes complicated (for example, if we add a sort function), it has to build its own producttableheader element. Now that we have identified the components in our use cases, we have layered them. Widgets in the component should behave as subclasses in the hierarchy.
Step 2:build a static version in React (Create a static release in React)
Now that our components are layered, it's time to implement our application. The simplest way to do this is to build a UI that is based on your data model, but does not have an interactive version. It is best to disassemble these steps, because creating a static version requires writing a lot of code without thinking, adding interaction requires a lot of thinking and writing very little code. Now you'll know why.
Build a static version of the app that renders your data model, and you'll want to build a component that can reuse other builds and pass data using props. Props is the way that fathers pass data down. If you are familiar with the concept of State, do not use state in this static version. State is only for the sake of interaction and the data inside is always changing. Altogether this is a static version, then do not use state.
You can build from the top down or the reverse, which means you can base your application hierarchy from the upper level to the bottom (for example, starting with filterableproducttable) or backwards (starting with productrow). In a simple example, it's easier from top to bottom, and it's easier to build and test the application from the bottom up in a large project.
At the end of this step, you will use a reusable component library to render your data model. Since this is a static version of an application, the component will only have the render () method. The component at the top of the component layer will use the data model as a prop. If you modify the underlying data model and then call Reactdom.render again (), the UI is updated. It's easy to see how your UI is updated, where it's changed, and then there's nothing complicated. React is based on unidirectional data streams that make everything modular and fast.
var ProductCategoryRow = React.createClass ({
render: function () {
return (<tr> <th colSpan = "2"> {this.props.category} </ th> </ tr>);
}
});
var ProductRow = React.createClass ({
render: function () {
var name = this.props.product.stocked?
this.props.product.name:
<span style = {{color: 'red'}}>
{this.props.product.name}
</ span>;
return (
<tr>
<td> {name} </ td>
<td> {this.props.product.price} </ td>
</ tr>
);
}
});
var ProductTable = React.createClass ({
render: function () {
var rows = [];
var lastCategory = null;
this.props.products.forEach (function (product) {
if (product.category! == lastCategory) {
rows.push (<ProductCategoryRow category = {product.category} key = {product.category} />);
}
rows.push (<ProductRow product = {product} key = {product.name} />);
lastCategory = product.category;
});
return (
<table>
<thead>
<tr>
<th> Name </ th>
<th> Price </ th>
</ tr>
</ thead>
<tbody> {rows} </ tbody>
</ table>
);
}
});
var SearchBar = React.createClass ({
render: function () {
return (
<form>
<input type = "text" placeholder = "Search ..." />
<p>
<input type = "checkbox" />
{''}
Only show products in stock
</ p>
</ form>
);
}
});
var FilterableProductTable = React.createClass ({
render: function () {
return (
<div>
<SearchBar />
<ProductTable products = {this.props.products} />
</ div>
);
}
});
var PRODUCTS = [
{category: 'Sporting Goods', price: '$ 49.99', stocked: true, name: 'Football'},
{category: 'Sporting Goods', price: '$ 9.99', stocked: true, name: 'Baseball'},
{category: 'Sporting Goods', price: '$ 29.99', stocked: false, name: 'Basketball'},
{category: 'Electronics', price: '$ 99.99', stocked: true, name: 'iPod Touch'},
{category: 'Electronics', price: '$ 399.99', stocked: false, name: 'iPhone 5'},
{category: 'Electronics', price: '$ 199.99', stocked: true, name: 'Nexus 7'}
];
ReactDOM.render (
<FilterableProductTable products = {PRODUCTS} />,
document.getElementById ('container')
);
Step 3: Identify the minimal (but complete) representation of UI state (find the representative of the minimal UI state)
In order to achieve the interactivity of your UI, you need to trigger changes to your underlying data model. React makes this easy by using state.
In order to properly create your application, the first step should consider the smallest unit of variable state your application requires. The key trick is: do n’t repeat. Find out the absolute minimum representative of the state required by your application, and then calculate all the other things you need. For example: if you are building a TODO list, then just save an array around the TODO items; do not save a state for the length of the array, if necessary, go to the array length.
Think about all the data fragments in our application. We have:
1. The most original product list
2. Search text entered by the user
3. The value of checkbox
4. Products being screened
Let's take a look at each one to find out which one is the state. Three questions are asked for each piece of data:
1. Are these props passed from their parents? If so, then it is not a state.
2. Is it changing in real time? If not, it is not a state.
3. Can you get it from other state or props in the component? If it can, it is not state.
The original product list is passed as props, it is not a state. The search text and checkbox look like state because they are changing in real time and cannot be derived from other data. Finally, the filtered product list is not a state, because it can be derived from the search text, checkbox and original product list.
Therefore, our state is: the value of the search text and checkbox.
Step 4: Identify where your state should live (confirm where your state should live)
Okay, so we have confirmed the smallest set of state in the application. Next, we need to confirm which component changes or owns this state. Remember, react is a one-way data flow in our component hierarchy. It may not be clear at a glance which component owns which state. This is often the most challenging part for novices, so follow the steps below to make it clear:
For each state in your application:
-Confirm that every component that depends on this state to render sth
-Find a component owner (in the component hierarchy, individual components located above all components also need this state)
-Whether it is the component owner or the upper component in the component layer should have this state
-If you can't find a component that owns this state, create a component whose function is to save this state, and place it above the component owner.
Let's try the above strategy in the current application.
-ProductTable needs to filter product list according to state, and SearchBar to display search text and checkbox state also need state.
-The component owner is FilterableProductTable.
-Putting filter text and checked value in FilterableProductTable is conceptually feasible.
Cool, we happily decided to put the state in the FilterableProductTable. First, add a getInitialState () method to FilterableProductTable. The return value is {filterText: ‘‘, inStockOnly: false}, reflecting the initial state of the application. Then, pass filterText and inStockOnly as props into ProductTable and SearchBar. Finally, use these props to filter the rows in ProductTable and set the
The value of the form field.
Now you can see how your application works: set filterText to "ball" and then refresh the application, you can see the data table is updated correctly.
var ProductCategoryRow = React.createClass ({
render: function () {
return (<tr> <th colSpan = "2"> {this.props.category} </ th> </ tr>);
}
});
var ProductRow = React.createClass ({
render: function () {
var name = this.props.product.stocked?
this.props.product.name:
<span style = {{color: 'red'}}>
{this.props.product.name}
</ span>;
return (
<tr>
<td> {name} </ td>
<td> {this.props.product.price} </ td>
</ tr>
);
}
});
var ProductTable = React.createClass ({
render: function () {
var rows = [];
var lastCategory = null;
this.props.products.forEach (function (product) {
if (product.name.indexOf (this.props.filterText) === -1 || (! product.stocked && this.props.inStockOnly)) {
return;
}
if (product.category! == lastCategory) {
rows.push (<ProductCategoryRow category = {product.category} key = {product.category} />);
}
rows.push (<ProductRow product = {product} key = {product.name} />);
lastCategory = product.category;
} .bind (this));
return (
<table><thead>
<tr>
<th> Name </ th>
<th> Price </ th>
</ tr>
</ thead>
<tbody> {rows} </ tbody>
</ table>
);
}
});
var SearchBar = React.createClass ({
render: function () {
return (
<form>
<input type = "text" placeholder = "Search ..." value = {this.props.filterText} />
<p>
<input type = "checkbox" checked = {this.props.inStockOnly} />
{''}
Only show products in stock
</ p>
</ form>
);
}
});
var FilterableProductTable = React.createClass ({
getInitialState: function () {
return {
filterText: '',
inStockOnly: false
};
},
render: function () {
return (
<div>
<SearchBar
filterText = {this.state.filterText}
inStockOnly = {this.state.inStockOnly}
/>
<ProductTable
products = {this.props.products}
filterText = {this.state.filterText}
inStockOnly = {this.state.inStockOnly}
/>
</ div>
);
}
});
var PRODUCTS = [
{category: 'Sporting Goods', price: '$ 49.99', stocked: true, name: 'Football'},
{category: 'Sporting Goods', price: '$ 9.99', stocked: true, name: 'Baseball'},
{category: 'Sporting Goods', price: '$ 29.99', stocked: false, name: 'Basketball'},
{category: 'Electronics', price: '$ 99.99', stocked: true, name: 'iPod Touch'},
{category: 'Electronics', price: '$ 399.99', stocked: false, name: 'iPhone 5'},
{category: 'Electronics', price: '$ 199.99', stocked: true, name: 'Nexus 7'}
];
ReactDOM.render (
<FilterableProductTable products = {PRODUCTS} />,
document.getElementById ('container')
);
STEP 5: Add inverse data flow
At this point, we have built an application that can correctly render based on the flow of state and prop between module layers. Now it's time to support another way of data flow: the form component in the deep level needs to update the state in the FilterableProductTable. This data flow in React is very clear and clear, so it is very easy to understand how your application works, but this requires more code to be written than the usual two-way data binding. React provides an additional tool called ReactLink to make this model as comfortable as two-way data binding. The purpose of this is to make everything clearer.
If you try to write code or check the checkbox in the latest version of the sample, you will see that React ignores your input. This is intentional, because we have set the input prop to be the same as the state passed by FilterableProductTable. Let's think about what kind of things we want to happen. We want to make sure that whenever the user changes the form, we update the state to reflect the user's input. Since components should only update their own state, FilterableProductTable will be passed to the SearchBar callback function, which will be called when the state needs to be updated. We can use the onchange event on the input to notify the call callback. The callback passed by FilterableProductTable will call setState () and the application will be updated.
Although this sounds complicated, it really only requires a few lines of code. And the flow of data in your application will be very clear. And that ‘s it.
I hope this article can help you figure out how to use React to build components and applications. Although this is more code than usual, remember that the readability of the code is much more important than the writing of the code. It is very easy to read these modular and very clear codes. When you start to build a large component library, you will appreciate this clarity and modularity, as the code is reused, your code size will start to decrease.
var ProductCategoryRow = React.createClass ({
render: function () {
return (<tr> <th colSpan = "2"> {this.props.category} </ th> </ tr>);
}
});
var ProductRow = React.createClass ({
render: function () {
var name = this.props.product.stocked?
this.props.product.name:
<span style = {{color: 'red'}}>
{this.props.product.name}
</ span>;
return (
<tr>
<td> {name} </ td>
<td> {this.props.product.price} </ td>
</ tr>
);
}
});
var ProductTable = React.createClass ({
render: function () {
var rows = [];
var lastCategory = null;
this.props.products.forEach (function (product) {
if (product.name.indexOf (this.props.filterText) === -1 || (! product.stocked && this.props.inStockOnly)) {
return;
}
if (product.category! == lastCategory) {
rows.push (<ProductCategoryRow category = {product.category} key = {product.category} />);
}
rows.push (<ProductRow product = {product} key = {product.name} />);
lastCategory = product.category;
} .bind (this));
return (
<table>
<thead>
<tr>
<th> Name </ th>
<th> Price </ th>
</ tr>
</ thead>
<tbody> {rows} </ tbody>
</ table>
);
}
});
var SearchBar = React.createClass ({
handleChange: function () {
this.props.onUserInput (
this.refs.filterTextInput.value,
this.refs.inStockOnlyInput.checked
);
},
render: function () {
return (
<form>
<input
type = "text"
placeholder = "Search ..."
value = {this.props.filterText}
ref = "filterTextInput"
onChange = {this.handleChange}
/>
<p>
<input
type = "checkbox"
checked = {this.props.inStockOnly}
ref = "inStockOnlyInput"
onChange = {this.handleChange}
/>
{''}
Only show products in stock
</ p>
</ form>
);
}
});
var FilterableProductTable = React.createClass ({
getInitialState: function () {
return {
filterText: '',
inStockOnly: false
};
},
handleUserInput: function (filterText, inStockOnly) {
this.setState ({
filterText: filterText,
inStockOnly: inStockOnly
});
},
render: function () {
return (
<div>
<SearchBar
filterText = {this.state.filterText}
inStockOnly = {this.state.inStockOnly}
onUserInput = {this.handleUserInput}
/>
<ProductTable
products = {this.props.products}
filterText = {this.state.filterText}
inStockOnly = {this.state.inStockOnly}
/>
</ div>
);
}
});
var PRODUCTS = [
{category: 'Sporting Goods', price: '$ 49.99', stocked: true, name: 'Football'},
{category: 'Sporting Goods', price: '$ 9.99', stocked: true, name: 'Baseball'},
{category: 'Sporting Goods', price: '$ 29.99', stocked: false, name: 'Basketball'},
{category: 'Electronics', price: '$ 99.99', stocked: true, name: 'iPod Touch'},
{category: 'Electronics', price: '$ 399.99', stocked: false, name: 'iPhone 5'},
{category: 'Electronics', price: '$ 199.99', stocked: true, name: 'Nexus 7'}
];
ReactDOM.render (
<FilterableProductTable products = {PRODUCTS} />,
document.getElementById ('container')
);
------------------------------------------------I'm Separator ------------------------------------------------ -
The original text ends.
This article mainly introduces the idea of React's unidirectional data flow based on an example of a product target. From the beginning, how to analyze the structure of the website model, how to divide the components, the data in the components, and the relationship between the data. According to these relationships, there are fixed To help us decide which data belongs to the state and which is prop. After the state is determined, you can add a monitoring method to the state-dependent components to monitor the input input changes, thereby updating the data model in real time and re-rendering the interface.
Thinking in React (translation)