How to use ternary condition to render jsx using react? - javascript

i want to return jsx if some condition is true if not undefined should be returned.
below is my code,
const showInfo = (item) {
return (
<div>
<div>
<span>name</span>
</div>
<div>
<button>click</button>
</div>
</div>
);
}
const Parent = () => {
return (
<Child
onDone = {({item}) => {
notify ({
actions: (condition === 'value1' || condition === 'value2' ) &&
showInfo(item) //should put this condition into showInfo method
})
}}
/>
);
}
what i am trying to do?
the above code works. but now i want to put the condition inside the showInfo method. so if condition is true return jsx and if condition is false should return undefined.
what i have tried?
I have tried something like below
const showInfo = (item) {
return
{(condition === 'value1' || condition === 'value2' ) ? <div>
<div>
<span>name</span>
</div>
<div>
<button>click</button>
</div>
</div>
: undefined
}
);
}
const Parent = () => {
return (
<Child
onDone = {({item}) => {
notify ({
actions: showInfo(item) //error here
})
}}
/>
);
}
but the above tried code, gives error "Type 'void' is not assignable to type 'ReactNode'" at actions statement.
could someone help me with this. i am not sure if i have used ternary operator properly. thanks.
EDIT
after trying one of the answers provided,
notify is a method that is returned from usehook
and it evaluates to the component below
const Something: React.FC<SomethingProps> = ({
description,
actions,
...props
}) =>
(
<Header>
<Title>{title}</Title>
</Header>
{(description ||actions) && (
<Body> //this is displayed
{description && <Description>{description}</Description>}
{actions && <Actions>{actions}</Actions>}
</Body>
)}
);
here the component is displayed when the condition fails in showInfo component.
in showInfo i am returning undefined if condition fails but still in the Something component the is displayed even though i have {description || actions}
i am not sure what is happening here.what is the condition i have to check for actions to not display in this case
i have tried
{(description ||actions !== 'false') && (
<Body> //this is displayed
{description && <Description>{description}</Description>}
{actions && <Actions>{actions}</Actions>}
</Body>
)}
and this works. i am wondering why i should specifically mention
actions !== 'false'
instead of actions only
could someone help me with this. thanks.

If you want to return jsx from function you should wrap them inside some component. In this case you cen use <React.Fragment> or just <>. Another problem which I can see is that you probably forgot about arrow in you arrow function. Also don't know from where variable names condition comes from.
const showInfo = (item) => {
return (
<>
{ condition === "value1" || condition === "value2" ? (
<div>
<div>
<span>name</span>
</div>
<div>
<button>click</button>
</div>
</div>
) : undefined}
</>
);
};

Wouldn't it be better to use the useState or useEffect hooks?

Related

React use parameters in jsx variable

I'm new to react and I'm trying to substitute a part of a jsx return I'm repeating in a react component, but there are slight differences in each repetition so I want to pass a simple boolean as a parameter to the variable so I can check those inside jsx. Here is what I've done so far:
function links(condition){
console.log("Condition is: " + condition);
return(<h1 className={`mr-10 ${ condition === true ? 'flex' : 'hidden' }`>Test</h1>);
}
const Navbar = () => {
return( <nav>
<div> {links.call(false)} </div>
<div> {links.call(true)} </div>
</nav>
); }
This returns Condition is: then Condition is: Undefined in the console. How can I achieve this?
Down there you can see the "proper" way of using react:
function Links({ condition }) {
return(
<h1 className={`mr-10 ${ condition === true ? 'flex' : 'hidden' }`>
Test
</h1>
);
}
const Navbar = () => {
return(
<nav>
<div>
<Links condition={false} />
</div>
<div>
<Links condition={true} />
</div>
</nav>
);
}
Note:
Better call you component with a caps: link => Link
To call a component use <Component {...props} />
The props (parameters) are passed as a object in the first parameter of the function

Wrap function in useCallback

In the code snippet below, I'd like to move this function out of jsx and wrap into useCallback.
{suggestedTags.length ? (
<div className={classes.tagSuggestionWrapper}>
{suggestedTags.map((tag) => {
return (<div key={tag}
onClick={() => { selectTag(tag) }}>{tag}</div>
);
})}
</div>
) : null }
Otherwise, a new function is created for every element on every render.
I understand that this may complicate the code, and may not be advisable. But I have to do it. I ask for your advice
You can do:
const selectTag = useCallback((tag) => {
setTags((prevState) => [...prevState, tag]);
setSuggestedTags([]);
setInput("");
}, [])
Little about useCallback
Bare in mind that if you had used any state variable, or prop, you should have included that in the dependency array. An empty dependency array makes sure selectTag reference will stay the same once the component mounts.
And no dependency array is the same as not using useCallback at all
Removing the arrow function
You can remove the arrow function by passing the value by using the onClick event function:
const selectTag = (event) => {
const tag = event.target.name
setTags((prevState) => [...prevState, tag]);
setSuggestedTags([]);
setInput("");
}
return (
{suggestedTags.length ? (
<div className={classes.tagSuggestionWrapper}>
{suggestedTags.map((tag) => {
return (<div key={tag}
name={tag}
className={classes.tagSuggestion}
onClick={selectTag}>{tag}</div>
);
})}
</div>
) : null }
</div>
);

Send value to child component in react

I have a component that takes a parameter that can be true or false, I put it in the console to check.
console.log(isContract);
//can be true ou false
I need to send this value through a form that will render another component.
This is the parent component:
return (
<Contract
savingsFactors={formValues.savingsFactors}
onFieldSubmit={...}
/>
)
And here in the internal component, if my value that came from the other component is true, I need to change the items
const Contract = ({ savingsFactors }) => (
<PutField
label={label}
placeholder={placeholder}
onBlur={...}
// if isContract === true, return this:
items={savingsFactors === 'true' ? FORM_VALUES : FORM_VALUES_NORMAL}
// if isContract === false, return this:
items={savingsFactors === 'true' ? ANOTHER_FORM_VALUES : ANOTHER_FORM_VALUES_NORMAL}
/>
);
What is the simplest way to send the isContract to the internal component and load the items according to the result?
I'm studying react and I'm having a lot of trouble with it, thanks a lot to those who help
I'm more familiar with defined props in React, but If I remember correctly, this should go something like this:
Edit 1
Added a render method inside the Contract component.
Edit 2
I just realized that you have a component inside your contract component XD which should be inside the render method itself. I think that might be the issue.
return (
<Contract
savingsFactors={formValues.savingsFactors}
isContract={isContract}
onFieldSubmit={...}
/>
)
And your component should be something like (After Edit 2):
const Contract = (props) => (
render(){
let items = [];
if (props.isContract === true)
{
items={props.savingsFactors === 'true' ? FORM_VALUES : FORM_VALUES_NORMAL}
}
//BTW, should this be !== true? :P
if (props.isContract === true)
{
items={props.savingsFactors === 'true' ? ANOTHER_FORM_VALUES : ANOTHER_FORM_VALUES_NORMAL}
}
return (
<div>
<h2>I have {items.length} items... or something...<h2>
<PutField
label={label}
placeholder={placeholder}
**items={items}** /*Maybe?*/
onBlur={...}
/>
</div>
)
}
);

have return statement and return nothing

i'm beginner on react(javascript), doing todo app, have a questions related to having a return inside if statement but returning nothing(if user writes nothing and press enter it does not count it), but when i take it away it will affect the behaviour of todo app. My question is what is the meaning of this part of the code if (!value) { return }
if there is no value it will return what ? and why taking away the 'return' it will change the behaviour of todo app ?
here is code:
import React, { useState } from 'react';
import './App.css';
function Todo({ tod, index }) {
return <div className="todo">{tod.text}</div>
}
function TodoForm({ addTodo }) {
const [value, setValue] = useState('');
console.log(value)
const handleSubmit = e => {
e.preventDefault();
if (!value) {
return
}
addTodo(value);
setValue('');
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
className="input"
value={value}
placeholder="Add Todo..."
onChange={e => setValue(e.target.value)}
/>
</form>
)
}
function App() {
const [todos, setTodos] = useState([
{
text: ' Learn by doing',
isCompleted: false
}
]);
const addTodo = text => {
const newTodos = [...todos, { text }];
setTodos(newTodos);
}
return (
<div className="app">
<div className="todo-List">
{todos.map((todo, index) =>
<Todo key={index} index={index} tod={todo} />
)}
<TodoForm addTodo={addTodo} />
</div>
</div>
)
}
export default App;
here i have javascript code where i'm trying to have same kind of statement as the code above ( if(!text){ return } )
here it does not matter if i have 'return' or dont have, it is the same both ways(why in previous example it was different ?)
:
function myFunction(text) {
var text=document.getElementById('text').value
event.preventDefault();
console.log(text);
if(!text){
return
}
else{
document.getElementById('demo').innerHTML = "Text typed: "+text; // if nothing
}}
<form onsubmit="myFunction()">
<input type="text" id="text" >
</form>
<p id="demo"></p>
English is not my mother language so sorry for mistakes.
Copying your code in question here:
const handleSubmit = e => {
e.preventDefault();
if (!value) {
return
}
addTodo(value);
setValue('');
}
This is considered a null check. What you're saying inside of that function is effectively "if this variable is true, don't proceed with the rest of the function and return as undefined". If your value variable equates to a value that is null or undefined in Javascript (attached link goes to a SO answer for the difference between null and undefined) then your ! operator will return true for the if statment again (as I said above) not running the rest of the function and returning undefined.
See this codepen here where if you toggle the variable "shouldRun" from true and false you'll either get the console log after the return, or undefined returned: https://codepen.io/kjscott27/pen/wvMbKJb?editors=1111
EDIT: I felt it was necessary to perhaps add additional sources for the difference between null and undefined. Additionally this resource has answers towards definitions of both terms directly from ECMA script and further reading, here in this other SO answer.
Adding onto kjs0's answer,
In Javascript, returning no value will be undefined. Example:
function myFunc() {
return;
}
myFunc() // the returned value is undefined

How to handle a generated big form in React Js

I trying to generate a big form based on what I get from the server.
sometimes I generate 32 elements sometimes 57 or 4 I don't know.
I try to create a component for each type of element like select, text, number, textarea and so on.
each component passes the value to the parent component and setState the value to the parent.
imagine I have 20 inputs and custom select-option elements.
when I type something in one of the inputs characters show up after 2seconeds and there is a huge lag in my component.
I know because of the setState method my hole component (I mean my parent component or my single source of truth) re-renders and causes the problem.
in fact, I don't know other ways.
I try to use a "this.VARIABLE" and instead of setState, I update the "this.VARIABLE" and problem solved. but I need my state.
any help or solution?
my code (parent Component, source of truth ):
// ---> find my component based on the type that I get from server
findComponent ( item , index) {
if ( item.type === 'text' || item.type === 'number') {
return (<Text data={item} getUpdated={this.fetchingComponentData} />);
} else if ( item.type === 'longtext') {
return (<Textarea data={item} getUpdated={this.fetchingComponentData} />);
} else if ( item.type === 'select' ) {
return (<SelectOption data={item} getUpdated={this.fetchingComponentData} />);
} else if ( item.type === 'autocomplete') {
return (<AutoTag data={item} url={URL1} getUpdated={this.fetchingComponentData} />);
} else if ( item.type === 'checkbox_comment' ) {
return (<CheckboxComment data={item} getUpdated={this.fetchingComponentData} />);
} else if ( item.type === 'multiselect' ) {
return (<Multiselect data={item} getUpdated={this.fetchingComponentData} />);
} else {
return (<p>THERE IS NO TYPE OF => {item.type}</p>);
}
}
// ----> if i setState here ==> big lag
fetchingComponentData(OBJ) {
let index = null;
// let Answer = [...this.state.Answer];
index = Helper.find_item(this.Answer , OBJ , 'unique_key');
if ( index === -1 ) {
this.Answer.push(OBJ);
} else {
this.Answer[index].value = OBJ.value;
}
}
// ----> in my render method
render () {
return (
<React.Fragment>
<div className="row Technical section" data-info="Technical">
<div className="col-6">
{data.map( (item,index) => {
return (
<React.Fragment key={index}>
<div className="rowi">
{item.attributes.map( (item, index)=> {
return <React.Fragment key={index}>{this.findComponent(item, index)}</React.Fragment>;
})}
</div>
</React.Fragment>
)
})}
</div>
<div className="col-6"></div>
</div>
</React.Fragment>
);
}
Have you tried to make an object out of your components and pass it to setState at once?
const nextState = componentList.map(component => {
return {[component]: value};
});
this.setState({...nextState});
Edit: Okay i got another part you could do better.
You should build an array with you components in componentWillMount function instead of fetching all the data inside the render. Like you said, it's updating everytime any state changes, and all the components are also updating with the parent.
This is to be made in addition with what I suggested before, but it is of far more importance because of the impact on the ressource.

Categories

Resources