React.createElement
, but with jsx it will turn out much more concise, which increases readability. And everything is great before the first need to display the data in a loop. In jsx cycles are not provided. But the insertion of js-code is provided. And here the question of readability arises again, but now it is significantly deteriorating. There is a situation when html is written in js-code, in which js-code is written with html. Of course, you can select html in a separate function. But then html will appear in the code here and there. And I would like to localize everything in one place. Fortunately, in modern javascript for almost any problem, there is a solution in the form of a library or a plugin. The above problem is easily solved by the babel transform-react-statements plugin.<For/>
, to js code. Suppose there is such a component: const MyComponent = props => <ul> <For each="item" in={props.items}> <li key={item.id}> {item.text} </li> </For> </ul>
var _this = this; const MyComponent = props => <ul> {Array.prototype.map.call(props.items, function (item, index) { return <li key={item.id}> {item.text} </li>; }, _this)} </ul>;
For
. The first attribute is in
. This is a required attribute that indicates how to get an object to be iterated (for example, a variable). The value must be an expression, i.e. enclosed in braces.each
specifies the name of the variable for each element of the array. It is not mandatory. In case of its absence, the elements of the array will be transmitted as a spread-attribute. <div> <For in={items}> <Item /> </For> </div>
<div> {Array.prototype.map.call(items, function (value, index) { return <Item {...value} />; }, this)} </div>
index
variable is available in the loop. You can rename a variable using the counter
attribute: <For each="row" counter="rowIndex" in={rows}> <div key={`row-${rowIndex}` className="row"> <For each="cell" counter="cellIndex" in="row"> <div key={`cell-${cellIndex}`} className="ceil"> { cell.content } </div> </For> </div> </For>
key
attribute. It can be specified obviously, as in the example above. Another way is to use the key-is
attribute. This may slightly improve readability. You can also specify keyIs
in the plugin parameters. Then key
will not need to be written in the template - the logic of its receipt goes into the business logic. { plugins: [["transform-react-statements", { keyIs: "id" }]] }
<div> <For each="item" in={array}> <div>{ item.value }</div> </For> <For each="item" in={array} key-is="someKey"> <div>{ item.value }</div> </For> <For each="item" in={array}> <div key={item.getKey()}>{ item.value }</div> </For> </div>
<div> {Array.prototype.map.call(array, function (item) { // key return <div key={item.id}>{item.value}</div>; }, this)} {Array.prototype.map.call(array, function (item) { // key - <For /> return <div key={item.someKey}>{item.value}</div>; }, this)} {Array.prototype.map.call(array, function (item) { // React return <div key={item.getKey()} key={item.id}>{item.value}</div>; }, this)} </div>;
<div> { condition && <Component /> } </div>
true
or false
, checking the condition for truth or falsity, respectively. For several child elements, the condition will apply to each of them: <div> <If false={someCondition}> <div> 1 </div> <div> 2 </div> </If> </div>
<div> { !someCondition && <div> 1 </div> } { !someCondition && <div> 2 </div> } </div>
Switch
behaves the same way as in javascript. The Switch
component has a value
attribute, the value of which should be an expression in curly brackets, and Case
child components, with their own value
attributes. If the value does not match any of the Case
values, the Default
block is displayed. If the Default
block is not present, null
returned. <div> <Switch value={x}> <Case value={“foo”}> <div> Text 1 </div> </Case> <Case value="bar"> <div> Text 2 </div> </Case> <Case value={1}> <div> Text 3 </div> </Case> <Default> <div> Default text </div> </Default> </Switch> </div>
<Component> <div> text </div> </Component>
props => <div> text </div>;
props
is available inside <Component/>
, which can be overridden through the props
attribute: <Component props="item"> <div {...item} /> </Component>
item => <div {...item} />;
class MyComponent extends React.Component { render() { return <For each="item" in={props.items}> <div key={item.id}> {item.text} </div> </For> } }
render
method should return a React element. In order to use such a component, the loop must be wrapped in an element. For example: class MyComponent extends React.Component { render() { return <div> <For each="item" in={props.items}> <div key={item.id}> {item.text} </div> </For> </div> } }
<span />
. This behavior can be changed by specifying the wrapper
parameter in the plugin settings: { plugins: [["transform-react-statements", { wrapper: '<div class=”wrapper” />' }]] }
no-wrap
parameter: { plugins: [["transform-react-statements", { wrapper: "no-wrap" }]] }
<If />
, which copes with its task. Then it can be disabled using the disabled
parameter: { plugins: [["transform-react-statements", { disabled: ["If"]}]] }
IfStatement
: { plugins: [["transform-react-statements", { rename: { "If": "IfStatement" } }]] }
Source: https://habr.com/ru/post/330172/
All Articles