Code duplication: how to avoid in Reactjs - reactjs

Expectation: if the flag is true, then empty div "container" around div "content"
const Demo = () => {
const [flagABC] = useFlagFeature(true)
return (
<div className="featureflagoff"> style= {} onMouseEnter = {} //if feature flag is off || if feature flag is ON then empty div
<div className="content">
// huge code
<div>
</div>
);
}
how can i avoid copying the ("huge code") twice.

Assign the huge code to a variable and reference it.
const hugeCode = <div>...</div>
return (
<div className="featureflagoff">
<div className="content">
{hugeCode}
<div>
</div>
);

Assuming flagABC is the flag, you can do something like this:
const Demo = () => {
const [flagABC] = useFlagFeature(true)
return (
<div className={flagABC ? "" : "featureflagoff"}>
<div className="content">
// huge code
<div>
</div>
);
}

Related

How can i render my function in React ? I can't render this

Function holding the ternary syntax and I can't able to render the content of the newElement function.
Used variables:
test1 = 1;
IstestString = true;
Render functions:
newElement = () => this.test1 === 1
? <h1>test is one</h1>
: <h1>test is not one </h1>;
render() {
return (
<div className='App'>
<p style={style}>{this.newElement}</p>
</div>
);
}
Someone can help me to find the problem here, please?
You need to return from your function in order to render jsx
Try something like below:-
newElement = () => {
return (
this.test1 === 1 ?
<h1> test is one</h1> : <h1>test is not one </h1>
)
}
render() {
return (
<div className='App'>
<p style={style}>{this.newElement()}</p> // add brackets here to call function
</div>
);
}
You just need to return a JSX element and avoid using render in a normal component function.
let NewElement = () => {
return (
<p style={{ display: "block" }}>
{true ? <h1>test is one</h1> : <h1>test is not one </h1>}
</p>
);
};
export default function App() {
return (
<div className="App">
<h1>A New Element</h1>
<NewElement />
</div>
);
}
Because you need a return value.
Also, be careful with your comparison. There's a difference between == and ===. The first one compares value but not type. The second one compares both value and type. Just look it up on google.
Note: You can keep your <p></p>, just for clarity's sake I excluded it (because technically it's not necessary but I don't know what you're trying to display)
newElement = () => {
let check = this.test1===1 ? <h1> test is one</h1> : <h1>test is not one</h1>
return check;
}
render() {
return (
<div className='App'>
{this.newElement()}
</div>
);
}

Content not displayed despite present data - React

Could you tell me why my offer content is always empty ?
The "toto" is not displayed and my data are displayed because of the line "console.log(offers").
const ListProduct = (offers : any) => {
console.log(offers);
const offersDisplay = offers ? (
<div>
{ () => {
console.log("test");
offers.map((shop :any) => {
shop.offers.map((offer:any) => {
return(
<div className="card border-secondary mb-3 listMaxWidth">
<div className="card-header">{shop.name}</div>
<div className="card-body">
<img src={offer.picture} className="imgOffer"/>
<h4 className="card-title">{offer.name}</h4>
<p className="card-text">{shop.description}</p>
</div>
</div>
);
});
})
}
}
</div>
):'toto';
return(
<div>
{offersDisplay }
</div>
)
}
export default ListProduct;
I tried so many different way to write it, unfortunately can't find the right way ...
Could you help me please ?
Thanks in advance
You don't need to pass a callback function in your code
const offersDisplay = offers ? (
<div>
//this callback
{ () => {
And also you don't return from your first map.
And the last thing is that you need to include the code in your return that way it gets executed every time the offers data is changed.
You need to change your code like this
const ListProduct = (offers : any) => {
return(
<div>
{
offers && offers.length && offers.map((shop :any) => {
return shop.offers.map((offer:any) => {
return(
<div className="card border-secondary mb-3 listMaxWidth">
<div className="card-header">{shop.name}</div>
<div className="card-body">
<img src={offer.picture} className="imgOffer"/>
<h4 className="card-title">{offer.name}</h4>
<p className="card-text">{shop.description}</p>
</div>
</div>
);
});
})
}
</div>
)
}
export default ListProduct;

Force update to make functional component re-render

I'm doing pokedex (pokemon wiki stuff). I want to change my component view, when clicking on pokemon images (description lookalike). When I click on an image - nothing happens (firstly, I want at least pokemon's name to be added to the pokemonDescription array). What am I doing wrong?
let pokemonDescription = [];
const useForceUpdate = () => {
const [value, setValue] = useState(true);
return () => setValue(value => !value);
}
const forceUpdate = useForceUpdate();
const onPokemonClick = (event) => {
console.log(
"wrapper clicked, event.target - ",
event.target.getAttribute('data-name')
);
pokemonDescription = [];
pokemonDescription.push(event.target.getAttribute('data-name'));
console.log("description array -", pokemonDescription);
forceUpdate();
};
useEffect(() => {
document.querySelector(".wrapper").addEventListener("click", onPokemonClick);
...
return () => {
document.querySelector(".wrapper").removeEventListener("click", onPokemonClick);
};
}, []);
...
return (
<div className="Pokemons">
<div className="column pokemons-list">
<div className="wrapper">
{
pokemonsData.map((p, id) => (
<div className="box" key={ id }>
<img
src={ p.sprites.front_default }
alt="pokemon-img"
title={ p.name }
className="icon"
data-name={p.name}
/>
{ p.name}
<div className="container">
{ pokemonsTypes[id] }
</div>
</div>
))
}
</div>
...
</div>
<div className="column description">
{ pokemonDescription }
</div>
</div>
)
You should add pokemonDescription to your component state
const [pokemonDescription, setPokemonDescription] = useState([]);
Remove the forceUpdate function and hook, it is unnecessary.
Attach the click handlers to the elements with the data-name attribute you are trying to handle.
Map the pokemonDescription state array to renderable JSX. I simply used a div, but you should use whatever your UI design requires.
const onPokemonClick = (event) => {
setPokemonDescription(names => [
...names,
event.target.getAttribute('data-name'),
]);
};
...
return (
<div className="Pokemons">
<div className="column pokemons-list">
<div className="wrapper">
{
pokemonsData.map((p, id) => (
<div className="box" key={ id }>
<img
src={ p.sprites.front_default }
alt="pokemon-img"
title={ p.name }
className="icon"
data-name={p.name}
onClick={onPokemonClick} // <-- attach click handler to img element
/>
{ p.name}
<div className="container">
{ pokemonsTypes[id] }
</div>
</div>
))
}
</div>
...
</div>
<div className="column description">
{pokemonDescription.map(name => (
<div>{name}</div>
))}
</div>
</div>
)
Add pokemonDescription to state instead of some local variable and it will solve your issue.
Try to avoid using forceUpdate, most of the times it means only that you are doing something silly.
I don't what that useForceUpdate does , but here is how would go about adding pokemon names to description array which is a state variable in my answer
const [pokemonDescription , setPokemonDescription ] = useState(null);
const onPokemonClick = (p) => {
const tempPokemonDescription = [...pokemonDescription ];
pokemonDescription.push(p.name);
console.log("description array -", pokemonDescription);
setPokemonDescription(tempPokemonDescription )
};
...
return (
<div className="Pokemons">
<div className="column pokemons-list">
<div className="wrapper">
{
pokemonsData.map((p, id) => (
<div className="box" onClick={e=>onPokemonClick(p)} key={ id }>
<img
src={ p.sprites.front_default }
alt="pokemon-img"
title={ p.name }
className="icon"
/>
{ p.name}
<div className="container">
{ pokemonsTypes[id] }
</div>
</div>
))
}
</div>
...
</div>
<div className="column description">
{ pokemonDescription }
</div>
</div>
)

setting variables in a map function

I have a function that returns this jsx mixed with some code like this:
showMedia = () => {
return (
<div>
{
<div id="mainContent">
{props.files.map((file) =>
const ext = fileExtension(file.name),
const icon = fileIcon(ext),
const isImg = isImage(ext),
<div key={file.id}>
<DisplayResults
fileId={file.id}
downloadName={file.downloadName}
fileTitle={file.title}
isImg={isImg}
icon={icon}
ext={ext}
/>
</div>
)}
</div>
}
</div>
);
}
In my editor, it's saying that it is expecting an '{' for the const variables I am setting after .map
Am I not using the correct syntax?
Thanks!
Since you don't have a function body {} for your arrow function, it is expecting an implicitly returned expression.
Give it a function body and declare your variables and return the JSX instead:
showMedia = () => {
return (
<div>
{
<div id="mainContent">
{props.files.map(file => {
const ext = fileExtension(file.name);
const icon = fileIcon(ext);
const isImg = isImage(ext);
return (
<div key={file.id}>
<DisplayResults
fileId={file.id}
downloadName={file.downloadName}
fileTitle={file.title}
isImg={isImg}
icon={icon}
ext={ext}
/>
</div>
);
})}
</div>
}
</div>
);
};
You have to add "return" in map function because map always expect to return something, so your problem can be solved by adding this
{props.files.map(file => {
return (
<div key={file.id}>
{/* something */}
</div>
);
})}
Hope this help

Extra div wrapper in map function

i need to create extra div wrapper for second and third element in React
I use a map function and i dont know how to fix it.
Here is a sandbox https://codesandbox.io/s/ojz6lvqnp6
And here is a what i need to achive
Another screen:
You need to change your code in your render method to
if (index !== 0) {
return (
<div key={index} className="second_wrapper">
<h1 >{index}</h1>
</div>
);
} else ....
EDIT:
You would need to change your code to :
render() {
const { members } = this.state;
return (
<div>
<div className="first_wrapper">
<h1 key={0}>{members[0].name}</h1>
</div>
<div className="second_wrapper">
{members.map((m, i) => {
if (i > 0) return <h1 key={i}>{m.name}</h1>;
})}
</div>
</div>
);
}
The new sandbox

Resources