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