Short circuiting not working in react render div - javascript

I want to start multiple components when a variable is true and I am using as follow:
return (
<div className="report">
{conditionalVariable &&
<ComponentA/> &&
<ComponentB/>
}
</div>
)
However, when the variable is true, only component A is getting up but not component B.What is wrong with this ?

I'm surprised you're getting any output. Those conditional components once you've worked out the logic, need to have a parent - either with a fragment, or a div, or something.
You would have seen something similar to this error:
SyntaxError: Inline Babel script: Adjacent JSX elements must be wrapped in an enclosing tag
const { Fragment, useState } = React;
function Example() {
const [ conditional, setConditional ] = useState(false);
function handleClick() {
setConditional(!conditional);
}
return (
<div>
{conditional && (
<Fragment>
<Test text="Bob" />
<Test text="Sue" />
</Fragment>
)}
<button onClick={handleClick}>
Click me
</button>
</div>
);
}
function Test({ text }) {
return <p>{text}</p>;
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Your curly braces are set rather strange. Try it like this:
return (
<div className="report">
{conditionalVariable &&
<>
<ComponentA />
<ComponentB />
</>
}
</div>
)
This solution uses the short syntax of React.Fragment to group the two components you want to display under the same condition.

Related

react nesting 3 components opening and closing tag where when the element inside the tag isnt rendered

I found a similar question here: React component closing tag
but i am still confuse...
why when I do this it doesnt work? innertherinner doesnt get rendered.
function Outer(props) {
return (
<Inner>
<InnerTheInner />
</Inner>
)
}
function Inner(props) {
return (
<>
</>
)
}
function InnerTheInner() {
return (
<>
innertheinner
</>
)
}
ReactDOM.render(
<React.StrictMode>
<Outer user='nishi' avatar='avatar photo' />
</React.StrictMode>,
document.getElementById('root')
);
isnt it equivalent to this:
<Outer>
<Inner>
<InnerTheInner>
InnerTheInner
</InnerTheInner>
</Inner>
</Outer>
You need
function Inner(props) {
return <>{props.children}</>;
}
else it would just render always
return (
<>
</>
)
Checkout https://reactjs.org/docs/composition-vs-inheritance.html
In fact you're rendering an empty Fragment using Inner component - without any child nodes. React components do not render its children inside unless you tell them to do so explicitly:
function Inner(props) {
return (
<>
{props.children}
</>
)
}
That way, every component that is passed inside the <Inner> will be rendered (as it's a part of the children prop).
Also you can simplify it, as there's no need to use Fragment at all, just return props.children and you're good to go.
function Inner(props) {
return props.children
}

eslint error about .jsx flie tag in vue-project when I npm run dev [duplicate]

I am trying to set up my React.js app so that it only renders if a variable I have set is true.
The way my render function is set up looks like:
render: function() {
var text = this.state.submitted ? 'Thank you! Expect a follow up at '+email+' soon!' : 'Enter your email to request early access:';
var style = this.state.submitted ? {"backgroundColor": "rgba(26, 188, 156, 0.4)"} : {};
return (
<div>
if(this.state.submitted==false)
{
<input type="email" className="input_field" onChange={this._updateInputValue} ref="email" value={this.state.email} />
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true}>
<div className="button-row">
<a href="#" className="button" onClick={this.saveAndContinue}>Request Invite</a>
</div>
</ReactCSSTransitionGroup>
}
</div>
)
},
Basically, the important portion here is the if(this.state.submitted==false) portion (I want these div elements to show up when the submitted variable is set to false).
But when running this, I get the error in the question:
Uncaught Error: Parse Error: Line 38: Adjacent JSX elements must be wrapped in an enclosing tag
What is the issue here? And what can I use to make this work?
You should put your component between an enclosing tag, Which means:
// WRONG!
return (
<Comp1 />
<Comp2 />
)
Instead:
// Correct
return (
<div>
<Comp1 />
<Comp2 />
</div>
)
Edit: Per Joe Clay's comment about the Fragments API
// More Correct
return (
<React.Fragment>
<Comp1 />
<Comp2 />
</React.Fragment>
)
// Short syntax
return (
<>
<Comp1 />
<Comp2 />
</>
)
It is late to answer this question but I thought It will add to the explanation.
It is happening because any where in your code you are returning two elements simultaneously.
e.g
return(
<div id="div1"></div>
<div id="div1"></div>
)
It should be wrapped in a parent element. e.g
return(
<div id="parent">
<div id="div1"></div>
<div id="div1"></div>
</div>
)
More Detailed Explanation
Your below jsx code get transformed
class App extends React.Component {
render(){
return (
<div>
<h1>Welcome to React</h1>
</div>
);
}
}
into this
_createClass(App, [{
key: 'render',
value: function render() {
return React.createElement(
'div',
null,
React.createElement(
'h1',
null,
'Welcome to React'
)
);
}
}]);
But if you do this
class App extends React.Component {
render(){
return (
<h1>Welcome to React</h1>
<div>Hi</div>
);
}
}
this gets converted into this (Just for illustration purpose, actually you will get error : Adjacent JSX elements must be wrapped in an enclosing tag)
_createClass(App, [{
key: 'render',
value: function render() {
return React.createElement(
'div',
null,
'Hi'
);
return React.createElement(
'h1',
null,
'Welcome to React'
)
}
}]);
In the above code you can see that you are trying to return twice from a method call, which is obviously wrong.
Edit- Latest changes in React 16 and own-wards:
If you do not want to add extra div to wrap around and want to return more than one child components you can go with React.Fragments.
React.Fragments (<React.Fragments>)are little bit faster and has less memory usage (no need to create an extra DOM node, less cluttered DOM tree).
e.g (In React 16.2.0)
render() {
return (
<>
React fragments.
<h2>A heading</h2>
More React fragments.
<h2>Another heading</h2>
Even more React fragments.
</>
);
}
or
render() {
return (
<React.Fragments>
React fragments.
<h2>A heading</h2>
More React fragments.
<h2>Another heading</h2>
Even more React fragments.
</React.Fragments>
);
}
or
render() {
return [
"Some text.",
<h2 key="heading-1">A heading</h2>,
"More text.",
<h2 key="heading-2">Another heading</h2>,
"Even more text."
];
}
React element has to return only one element. You'll have to wrap both of your tags with another element tag.
I can also see that your render function is not returning anything. This is how your component should look like:
var app = React.createClass({
render () {
/*React element can only return one element*/
return (
<div></div>
)
}
})
Also note that you can't use if statements inside of a returned element:
render: function() {
var text = this.state.submitted ? 'Thank you! Expect a follow up at '+email+' soon!' : 'Enter your email to request early access:';
var style = this.state.submitted ? {"backgroundColor": "rgba(26, 188, 156, 0.4)"} : {};
if(this.state.submitted==false) {
return <YourJSX />
} else {
return <YourOtherJSX />
}
},
If you don't want to wrap it in another div as other answers have suggested, you can also wrap it in an array and it will work.
// Wrong!
return (
<Comp1 />
<Comp2 />
)
It can be written as:
// Correct!
return (
[<Comp1 />,
<Comp2 />]
)
Please note that the above will generate a warning: Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'YourComponent'.
This can be fixed by adding a key attribute to the components, if manually adding these add it like:
return (
[<Comp1 key="0" />,
<Comp2 key="1" />]
)
Here is some more information on keys:Composition vs Inheritance
The problem
Parse Error: Adjacent JSX elements must be wrapped in an enclosing tag
This means that you are trying to return multiple sibling JSX elements in an incorrect manner. Remember that you are not writing HTML, but JSX! Your code is transpiled from JSX into JavaScript. For example:
render() {
return (<p>foo bar</p>);
}
will be transpiled into:
render() {
return React.createElement("p", null, "foo bar");
}
Unless you are new to programming in general, you already know that functions/methods (of any language) take any number of parameters but always only return one value. Given that, you can probably see that a problem arises when trying to return multiple sibling components based on how createElement() works; it only takes parameters for one element and returns that. Hence we cannot return multiple elements from one function call.
So if you've ever wondered why this works...
render() {
return (
<div>
<p>foo</p>
<p>bar</p>
<p>baz</p>
</div>
);
}
but not this...
render() {
return (
<p>foo</p>
<p>bar</p>
<p>baz</p>
);
}
it's because in the first snippet, both <p>-elements are part of children of the <div>-element. When they are part of children then we can express an unlimited number of sibling elements. Take a look how this would transpile:
render() {
return React.createElement(
"div",
null,
React.createElement("p", null, "foo"),
React.createElement("p", null, "bar"),
React.createElement("p", null, "baz"),
);
}
Solutions
Depending on which version of React you are running, you do have a few options to address this:
Use fragments (React v16.2+ only!)
As of React v16.2, React has support for Fragments which is a node-less component that returns its children directly.
Returning the children in an array (see below) has some drawbacks:
Children in an array must be separated by commas.
Children in an array must have a key to prevent React’s key warning.
Strings must be wrapped in quotes.
These are eliminated from the use of fragments. Here's an example of children wrapped in a fragment:
render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}
which de-sugars into:
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
Note that the first snippet requires Babel v7.0 or above.
Return an array (React v16.0+ only!)
As of React v16, React Components can return arrays. This is unlike earlier versions of React where you were forced to wrap all sibling components in a parent component.
In other words, you can now do:
render() {
return [<p key={0}>foo</p>, <p key={1}>bar</p>];
}
this transpiles into:
return [React.createElement("p", {key: 0}, "foo"), React.createElement("p", {key: 1}, "bar")];
Note that the above returns an array. Arrays are valid React Elements since React version 16 and later. For earlier versions of React, arrays are not valid return objects!
Also note that the following is invalid (you must return an array):
render() {
return (<p>foo</p> <p>bar</p>);
}
Wrap the elements in a parent element
The other solution involves creating a parent component which wraps the sibling components in its children. This is by far the most common way to address this issue, and works in all versions of React.
render() {
return (
<div>
<h1>foo</h1>
<h2>bar</h2>
</div>
);
}
Note: Take a look again at the top of this answer for more details and how this transpiles.
React 16.0.0 we can return multiple components from render as an array.
return ([
<Comp1 />,
<Comp2 />
]);
React 16.2.0 > we can return multiple components from render in a Fragment tag. Fragment
return (
<React.Fragment>
<Comp1 />
<Comp2 />
</React.Fragment>);
React 16.2.0 > you can use this shorthand syntax. (some older tooling versions don’t support it so you might want to explicitly write <Fragment> until the tooling catches up.)
return (
<>
<Comp1 />
<Comp2 />
</>)
If you do not wrap your component then you can write it as mentioned below method.
Instead of:
return(
<Comp1 />
<Comp2 />
);
you can write this:
return[(
<Comp1 />
),
(
<Comp2 />
) ];
it's very simple we can use a parent element div to wrap all the element
or we can use the Higher Order Component( HOC's ) concept i.e very useful for
react js applications
render() {
return (
<div>
<div>foo</div>
<div>bar</div>
</div>
);
}
or another best way is HOC its very simple not very complicated
just add a file hoc.js in your project and simply add these codes
const aux = (props) => props.children;
export default aux;
now import hoc.js file where you want to use, now instead of wrapping with div
element we can wrap with hoc.
import React, { Component } from 'react';
import Hoc from '../../../hoc';
render() {
return (
<Hoc>
<div>foo</div>
<div>bar</div>
</Hoc>
);
}
There is a rule in react that a JSX expression must have exactly one outermost element.
wrong
const para = (
<p></p>
<p></p>
);
correct
const para = (
<div>
<p></p>
<p></p>
</div>
);
React 16 gets your return as an array so it should be wrapped by one element like div.
Wrong Approach
render(){
return(
<input type="text" value="" onChange={this.handleChange} />
<button className="btn btn-primary" onClick= {()=>this.addTodo(this.state.value)}>Submit</button>
);
}
Right Approach (All elements in one div or other element you are using)
render(){
return(
<div>
<input type="text" value="" onChange={this.handleChange} />
<button className="btn btn-primary" onClick={()=>this.addTodo(this.state.value)}>Submit</button>
</div>
);
}
React components must wrapperd in single container,that may be any tag
e.g. "< div>.. < / div>"
You can check render method of ReactCSSTransitionGroup
Import view and wrap in View. Wrapping in a div did not work for me.
import { View } from 'react-native';
...
render() {
return (
<View>
<h1>foo</h1>
<h2>bar</h2>
</View>
);
}
Invalid: Not only child elements
render(){
return(
<h2>Responsive Form</h2>
<div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
<div className="col-sm-4 offset-sm-4">
<form id="contact-form" onSubmit={this.handleSubmit.bind(this)} method="POST">
<div className="form-group">
<label for="name">Name</label>
<input type="text" className="form-control" id="name" />
</div>
<div className="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
</div>
<div className="form-group">
<label for="message">Message</label>
<textarea className="form-control" rows="5" id="message"></textarea>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
)
}
Valid: Root element under child elements
render(){
return(
<div>
<h2>Responsive Form</h2>
<div>Adjacent JSX elements must be wrapped in an enclosing tag</div>
<div className="col-sm-4 offset-sm-4">
<form id="contact-form" onSubmit={this.handleSubmit.bind(this)} method="POST">
<div className="form-group">
<label for="name">Name</label>
<input type="text" className="form-control" id="name" />
</div>
<div className="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
</div>
<div className="form-group">
<label for="message">Message</label>
<textarea className="form-control" rows="5" id="message"></textarea>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
</div>
)
}
Just add
<>
// code ....
</>
For Rect-Native developers. I encounter this error while renderingItem in FlatList. I had two Text components. I was using them like below
renderItem = { ({item}) =>
<Text style = {styles.item}>{item.key}</Text>
<Text style = {styles.item}>{item.user}</Text>
}
But after I put these tow Inside View Components it worked for me.
renderItem = { ({item}) =>
<View style={styles.flatview}>
<Text style = {styles.item}>{item.key}</Text>
<Text style = {styles.item}>{item.user}</Text>
</View>
}
You might be using other components but putting them into View may be worked for you.
I think the complication may also occur when trying to nest multiple Divs within the return statement. You may wish to do this to ensure your components render as block elements.
Here's an example of correctly rendering a couple of components, using multiple divs.
return (
<div>
<h1>Data Information</H1>
<div>
<Button type="primary">Create Data</Button>
</div>
</div>
)

React EsLint - Component should be written as pure function and after changed it to pure function can't read the property anymore

So I have this simple class before I change it to pure function as eslint told me to do
class user extends Component {
render(){
return(
<Aux>
<UserTable title="User" type="user" role={this.props.location.roleAction}/>
</Aux>
)
}
}
export default user;
and then I got the eslint error said that component should be written as pure function and I try to change that to pure function like down bellow
const user = () => (
<Aux>
<UserTable title="User" type="user" role={this.props.location.roleAction} />
</Aux>
);
export default user;
and after change it to arrow function, I can't read the this.props.location.roleAction I got an error "cannot read property "location" of undefined " .why is that could happen? any solution to fix the error so I can using the arrow function and able to read the property. it work fine when I use the previous written component.
any help would be really appreciate.
In the pure function ("Stateless Functional Component" or SFC) form, you receive props as a parameter:
const user = props => ( // <−−−− Here
<Aux>
<UserTable title="User" type="user" role={props.location.roleAction} />
^−−−−−− no `this` here since it's
a parameter
</Aux>
);
This is covered in the docs here. Here's a simple runnable example:
const Example = props => (
<div>{props.text}</div>
);
ReactDOM.render(
<div>
<Example text="one" />
<Example text="two" />
</div>,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Can't delete the item I am clicking the delete button for - React [duplicate]

Lets say I have a view component that has a conditional render:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
MyInput looks something like this:
class MyInput extends React.Component {
...
render(){
return (
<div>
<input name={this.props.name}
ref="input"
type="text"
value={this.props.value || null}
onBlur={this.handleBlur.bind(this)}
onChange={this.handleTyping.bind(this)} />
</div>
);
}
}
Lets say employed is true. Whenever I switch it to false and the other view renders, only unemployment-duration is re-initialized. Also unemployment-reason gets prefilled with the value from job-title (if a value was given before the condition changed).
If I change the markup in the second rendering routine to something like this:
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
It seems like everything works fine. Looks like React just fails to diff 'job-title' and 'unemployment-reason'.
Please tell me what I'm doing wrong...
Change the key of the component.
<Component key="1" />
<Component key="2" />
Component will be unmounted and a new instance of Component will be mounted since the key has changed.
Documented on You Probably Don't Need Derived State:
When a key changes, React will create a new component instance rather than update the current one. Keys are usually used for dynamic lists but are also useful here.
What's probably happening is that React thinks that only one MyInput (unemployment-duration) is added between the renders. As such, the job-title never gets replaced with the unemployment-reason, which is also why the predefined values are swapped.
When React does the diff, it will determine which components are new and which are old based on their key property. If no such key is provided in the code, it will generate its own.
The reason why the last code snippet you provide works is because React essentially needs to change the hierarchy of all elements under the parent div and I believe that would trigger a re-render of all children (which is why it works). Had you added the span to the bottom instead of the top, the hierarchy of the preceding elements wouldn't change, and those element's wouldn't re-render (and the problem would persist).
Here's what the official React documentation says:
The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a key.
When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).
You should be able to fix this by providing a unique key element yourself to either the parent div or to all MyInput elements.
For example:
render(){
if (this.state.employed) {
return (
<div key="employed">
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div key="notEmployed">
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
OR
render(){
if (this.state.employed) {
return (
<div>
<MyInput key="title" ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<MyInput key="reason" ref="unemployment-reason" name="unemployment-reason" />
<MyInput key="duration" ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
Now, when React does the diff, it will see that the divs are different and will re-render it including all of its' children (1st example). In the 2nd example, the diff will be a success on job-title and unemployment-reason since they now have different keys.
You can of course use any keys you want, as long as they are unique.
Update August 2017
For a better insight into how keys work in React, I strongly recommend reading my answer to Understanding unique keys in React.js.
Update November 2017
This update should've been posted a while ago, but using string literals in ref is now deprecated. For example ref="job-title" should now instead be ref={(el) => this.jobTitleRef = el} (for example). See my answer to Deprecation warning using this.refs for more info.
Use setState in your view to change employed property of state. This is example of React render engine.
someFunctionWhichChangeParamEmployed(isEmployed) {
this.setState({
employed: isEmployed
});
}
getInitialState() {
return {
employed: true
}
},
render(){
if (this.state.employed) {
return (
<div>
<MyInput ref="job-title" name="job-title" />
</div>
);
} else {
return (
<div>
<span>Diff me!</span>
<MyInput ref="unemployment-reason" name="unemployment-reason" />
<MyInput ref="unemployment-duration" name="unemployment-duration" />
</div>
);
}
}
I'm working on Crud for my app. This is how I did it Got Reactstrap as my dependency.
import React, { useState, setState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import firebase from 'firebase';
// import { LifeCrud } from '../CRUD/Crud';
import { Row, Card, Col, Button } from 'reactstrap';
import InsuranceActionInput from '../CRUD/InsuranceActionInput';
const LifeActionCreate = () => {
let [newLifeActionLabel, setNewLifeActionLabel] = React.useState();
const onCreate = e => {
const db = firebase.firestore();
db.collection('actions').add({
label: newLifeActionLabel
});
alert('New Life Insurance Added');
setNewLifeActionLabel('');
};
return (
<Card style={{ padding: '15px' }}>
<form onSubmit={onCreate}>
<label>Name</label>
<input
value={newLifeActionLabel}
onChange={e => {
setNewLifeActionLabel(e.target.value);
}}
placeholder={'Name'}
/>
<Button onClick={onCreate}>Create</Button>
</form>
</Card>
);
};
Some React Hooks in there

Using jQuery inside of a React render function

I have the following React render function:
render: function () {
return (
<Popup onClose={this.props.onClose}>
<Form entity="strategy" edit="/strategies/edit/" add="/strategies/add/">
<h2>Create/Edit Strategy</h2>
<StrategyForm pending={this.state.pending} formData={this.state.data} />
<div className="col-md-6">
<Assisting />
</div>
</Form>
</Popup>
);
}
I would like to make the h2 heading be based on the body class, so my question is...can I do this?
render: function () {
return (
<Popup onClose={this.props.onClose}>
<Form entity="strategy" edit="/strategies/edit/" add="/strategies/add/">
if ( $('body').hasClass("this") ) {
<h2>Create This Strategy</h2>
} else {
<h2>Create Another Strategy</h2>
}
<StrategyForm pending={this.state.pending} formData={this.state.data} />
<div className="col-md-6">
<Assisting />
</div>
</Form>
</Popup>
);
}
If this is a terrible idea, can someone tell me what is a better way to do this in React?
As has already been noted in some of the comments on the OP, you could do it, but it's not really the "React" way.
A better solution would probably be to pass a prop into the usage of your component or have a flag on the state of your component -- then use that prop/flag to render.
Pseudocode:
render() {
return (
if (this.props.someProp) {
<h2>Create this Strategy</h2>
} else {
<h2>Create this Strategy</h2>
}
);
}
IMO using jQuery in the component methods is fine (e.g. componentDidMount(), or other event/utility methods) but usually you'll want to avoid this in render(). The whole purpose of React components is maintaining state, so on-the-fly usage of jQuery like your example defeats that idea.
Let's say for example you're rendering your component this way:
ReactDOM.render(<MyComponent />, document.getElementById('some-div'));
You can pass properties to your component:
ReactDOM.render(
<MyComponent someProp={true} />,
document.getElementById('some-div')
);
Or in your case:
ReactDOM.render(
<MyComponent someProp={$('body').hasClass("this")} />,
document.getElementById('some-div')
);
...something like that. It's an over-simplified example (not tested, so beware syntax errors) but that should help explain my thought process.
Alternatively, you use the componentDidMount() method on your class.
componentDidMount() {
this.setState({
someProp : $('body').hasClass("this")
});
}
and then in render() check against this.state.someProp.

Categories