Conditionally rendering multiple components -- which style is more readable? [closed] - javascript

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Consider a web app page where there's table of data that I can edit if I have sufficient permissions. For this example, our editing is limited to selecting and deleting rows.
Which of the following two approaches for the render method of each table row is more readable?
render() {
let checkbox, deleteButton;
if (CAN_EDIT) {
checkbox = (
<checkbox-button-stuff
... this is an 8 line declaration
...
...
...
...
...
...
...
/>
);
deleteButton = (
<delete-button-stuff
... this is a 9 line declaration
...
...
...
...
...
...
...
/>
);
}
return (
<div>
{checkbox}
<other-table-stuff />
{deleteButton}
</div>
);
}
or
render() {
let checkbox = (
<checkbox-button-stuff
... this is a 9 line declaration
...
...
...
...
...
...
/>
);
let deleteButton = (
<delete-button-stuff
... this is an 9 line declaration
...
...
...
...
...
...
...
...
/>
);
if (!CAN_EDIT) {
checkbox = null;
deleteButton = null;
}
return (
<div>
{checkbox}
<other-table-stuff />
{deleteButton}
</div>
);
}
Note: the *-stuff names are used to represent nested divs + other components. Also, I say that the buttons are an "X line declaration" because this is based on actual code review from a PR that I made.
I'd argue that the latter keeps the logic of "should I render these?" in one place. The first example, however, avoids the negation (!CAN_EDIT) which IMO hurts readability.
Thanks for any input!

For inline if else test in React, you can use :
render() {
{
<div>
MY_CONDITION ?
<MyComponentToRenderIfTrue />
:
<MyOtherComponentToRenderIfFalse />
</div>
}
}
OR
render() {
{
<div>
MY_CONDITION && <MyComponentToRender />
</div>
}
}
In both, you can update your MY_CONDITION and React will re-render your component.
Hope this help.

Here's a third option:
return (
<div>
{ CAN_EDIT && <CheckboxButtonStuff /> }
<OtherTableStuff />
{ CAN_EDIT && <DeleteButtonStuff /> }
</div>
);
Also your components should be capitalized and preferably camel cased- https://reactjs.org/docs/jsx-in-depth.html#html-tags-vs.-react-components

Related

Reactjs - how can i make line break in template strings and return for rendering?

You need to display the following content formatted on the screen:
divs:
<div>my text</div> <div>my text</div>
i tried to do this, but everything came out without line break:
const HtmlCreator=()=>{
let text="my text";
return (`divs: \n <div>${text}</div> <div>${text}</div> `)
{
return (
<div>
<p><HtmlCreator/></p>
</div>
)
Add whiteSpace:'pre' to your style :
<p style={{whiteSpace:'pre'}}><HtmlCreator /></p>
this is useful when you cannot modify the original data.
You can use <br />, but you'll need a wrapper. For that, you can use <React.Fragment>:
import React, { Fragment } from "react";
const HtmlCreator = () => {
let text = "my text";
return (
<Fragment>
divs
<br />
{`<div>${text}</div> <div>${text}</div>`}
</Fragment>
);
};
CodeSandbox Example
Your question implies you'd like to show the HTML itself (escape it) and not render it. If you meant the latter, you could do:
const HtmlCreator = () => {
let text = "my text";
return (
<Fragment>
divs
<br />
<div>{text}</div>
<div>{text}</div>
</Fragment>
);
};
CodeSandbox Example

Child state updated but not rendering [duplicate]

This question already has answers here:
map is not rendering the ui elements in reactjs
(2 answers)
Closed 2 years ago.
I have a child component named Recently Opened. There are no props passed to the child component from parent component. The rendor method of parent component is:
render() {
return (
<div>
<RecentlyOpened />
</div>
);
}
The render method of child component(RecentlyOpened) looks like this:
render() {
return (
<div className='outer-box'>
{this.state.items.map(item => {
<div className='item-box'>
<img className='image' src={'/src/assets/' + item.imgURL} />
<div className='name item-margin'>{item.name}</div>
<div className='id item-margin'><b>SKU/ID: </b>{item.productId}</div>
</div>;
})}
</div >
);
}
Here this.state.items is populated from an API call. But even as the state is updated(I have checked this) after the API call returns the data, the UI inside the map function doesn't get displayed and just the empty div is rendered. Shouldn't the UI be updated once the state of child component changes?
You are not returning a value in your map loop. A simple fix is to replace the curly brackets with parentheses.
render() {
return (
<div className='outer-box'>
{this.state.items.map(item => (
<div className='item-box'>
<img className='image' src={'/src/assets/' + item.imgURL} />
<div className='name item-margin'>{item.name}</div>
<div className='id item-margin'><b>SKU/ID: </b>{item.productId}</div>
</div>;
))}
</div >
);
}

How to add a <br> tag in reactjs between two strings?

I am using react. I want to add a line break <br> between strings
'No results' and 'Please try another search term.'.
I have tried 'No results.<br>Please try another search term.'
but it does not work, I need to add the <br> in the html.
Any ideas how to solve it?
render() {
let data = this.props.data;
let isLoading = this.props.isLoading;
let isDataEmpty = Object.entries(data).length === 0;
let movieList = isLoading ? <Loader /> : isDataEmpty ? 'No results. Please try another search term.' :
Object.entries(data).map((movie, index) => <MovieTile key={index} {...movie[1]} />);
return (
<div className='movieList'>{movieList}</div>
);
}
You should use JSX instead of string:
<div>No results.<br />Please try another search term.</div>
Because each jsx should have 1 wrapper I added a <div> wrapper for the string.
Here it is in your code:
render() {
let data = this.props.data;
let isLoading = this.props.isLoading;
let isDataEmpty = Object.entries(data).length === 0;
let movieList = isLoading ? <Loader /> : isDataEmpty ? <div>No results.<br />Please try another search term.</div> :
Object.entries(data).map((movie, index) => <MovieTile key={index} {...movie[1]} />);
return (
<div className='movieList'>{movieList}</div>
);
}
You can use CSS white-space to solve the problem.
React Component
render() {
message = `No results. \n Please try another search term.`;
return (
<div className='new-line'>{message}</div>
);
}
CSS
.new-line {
white-space: pre-line;
}
OUTPUT
No results.
Please try another search term.
break text to line:
render() {
...
<div>
{this.props.data.split('\n').map( (it, i) => <div key={'x'+i}>{it}</div> )}
</div>
...
Some HTML elements such as <img> and <input> use only one tag. Such tags that belong to a single-tag element aren't an opening tag nor a closing tag. Those are self-closing tags.
In JSX, one has to include the slash. So, remove <br> and try <br />
Here is how I got around this. Let message be the prop/variable that has the string containing line breaks to be displayed in HTML as follows:
message = 'No results.<br>Please try another search term.';
<div>
{message}
</div>
To make this work, we need to use \n instead of break tag <br> and set the following css on the wrapper element of this message as follows:
message = 'No results.\nPlease try another search term.';
<div className="msg-wrapper">
{message}
</div>
CSS:
.msg-wrapper {
white-space: pre-wrap;
}
OUTPUT:
No results.
Please try another search term.
If you don't want put the string inside a <div> you could use <> to do it.
Like this:
var text = <>This is a text in the first line;<br />this is a text in a second line</>;
Just split text by /n, I do this in this way:
<div>
{text.split('\n').map((item, i) => <p key={i}>{item}</p>)}
</div>
Try with span
return (
<div className='movieList'><span>{movieList}</span></div>
);
If you are like in my situation and you don't want to add css, you can do that :
render () {
...
return (
...
<Typography component="p">
...
{(contact.lastname)?<div>Hello {contact.firstname} {contact.lastname}</div>:''}
...
</Typography>
...
);
}
using ` worked for me however i am not sure if it is the exact solution to the problem :
import React from 'react';
import ReactDOM from 'react-dom';
let element = (
<div>
<h1> Hello world</h1>
This is just a sentence <br></br>
But This line should not be in the same previous line. <br></br>
The above content proves its working. <br></br>
npm v6.14.6 | react : {React.version}
</div>
);
ReactDOM.render(element,document.getElementById("html-element-id"))
You can add a span tag and add block as a class.
Pomodoro Technique Timer <span className="block">with Bla</span>
The simplest thing which I did is by creating a component.
const EmptySpace = ({ spaceCount = 0 }) => {
return (
<>
{Array.from({ length: spaceCount }, (item, index) => {
return <br key={index} />;
})}
</>
);
};
export default EmptySpace;
<EmptySpace spaceCount={1} />
In your case you could do something like this:
const msg = (
<p>
No results <EmptySpace spaceCount={2} />
Please try another search term.
</p>
);

Show character limit under input in React Js

I am creating a react input component and need to show the character limit underneath the input ex: (0/500 characters remaining). I have passed the maxLength as a prop into the input component but am unsure of how to show the number of characters remaining before the limit is reached.
The max length works properly - how can I add the visual feedback of showing how many characters are remaining (2/500 characters... etc).
<input
{...customAttributes}
maxLength={maxLength}
required={required}
/>
And then I call my component like so:
<InputComponent maxLength={10} />
The question does not have enough information to answer correctly, but based on the reaction to the comment, something like this should work:
<div>
{this.props.maxLength - this.state.whateverYouNamedTheValue.length}/{this.props.maxLength}
</div>
In the context of a component, cleaned up with ES6 a bit:
class InputComponent extends React.Component {
// ... class and state stuff ...
render() {
const { maxLength } = this.props;
const { whateverYouNamedTheValue } = this.state;
return (
<div>
<input
{...customAttributes}
maxLength={maxLength}
required={required}
/>
{ whateverYouNamedTheValue ? (
<div>
({ maxLength - whateverYouNamedTheValue.length }/{ maxLength })
</div>
) : null }
</div>
);
}
}

Create a quick Weather widget app using Reactjs [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I was wondering if there is an example of weather widget that can be created quickly and it would be better if it is lightweight.
I wanted to share some concepts of creating an application using JavaScript, Jquery and Reactjs. Which can help learning quickly than any other sources. Here is what I did using Reactjs:
HTML:
<div style="width: 310px;display: block;float: left; padding: 20px;">
<div id="weather-app"></div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-with-addons.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js'></script>
<script src="script.js"></script>
JS:
var Main = React.createClass({
getInitialState: function(){
return {
isLoading: true,
toggleForm: false,
isError: false
}
},
setError: function(value){
this.setState({isError: value});
},
changeLoading: function(value){
this.setState({isLoading: value});
},
onToggleForm: function(value){
this.setState({toggleForm: value});
},
onFormSubmit: function(c, s){
this.onToggleForm(false);
this.refs.change.toggleForm();
this.refs.front.reRender(c, s);
this.setState({isError: false});
},
render: function(){
return (
<div id="weather" className="weather">
<ChangeBtn ref="change" isLoading={this.state.isLoading} toggleForm={this.onToggleForm} />
<Front ref="front" isLoading={this.state.isLoading} isError={this.state.isError} setError={this.setError} loadCallback={this.changeLoading} toggle={this.state.toggleForm} />
<Form isLoading={this.state.isLoading} toggle={this.state.toggleForm} onFormSubmit={this.onFormSubmit} isError={this.state.isError} setError={this.setError} />
<Spinner isLoading={this.state.isLoading} />
</div>
)
}
})
ReactDOM.render(<Main />, document.getElementById("weather-app"));
1) Above code is preview only. Full Example can be found at this plnkr1 link.
2) I created same example using Jquery here: plnkr2
3) I wondered, what if I build the same using native JavaScript for extremely lightweight application? Then I also created the same using pure JavaScript here: plnkr3

Categories

Resources