I'm building this site and right now i have 4 divs that do basically the same thing, but theyre being copy and pasted 4 times and just like 4 bits of information are being changed from them. is there any way using react that i can make it so its only one div and a function handles the different parameters needed for the divs? here is is a quick example.
quickExample.jsx
import React, {useRef} from "react";
function test(props) {
animalAmount = useRef(20);
return (
<div>
<div id='turtle-id'>
<h1>I like turtles!</h1>
<p>there are {animalAmount.current} turtles in my house!</p>
<button>Click me!</button>
</div>
<div id='dog-id'>
<h1>I like dogs!</h1>
<p>there are {animalAmount.current} dogs in my house!</p>
<button>Click me!</button>
</div>
<div id='fish-id'>
<h1>I like fish!</h1>
<p>there are {animalAmount.current} fish in my house!</p>
<button>Click me!</button>
</div>
<div id='hippo-id'>
<h1>I like hippos!</h1>
<p>there are {animalAmount.current} hippos in my house!</p>
<button>Click me!</button>
</div>
</div>
);
}
export default test;
for specific reasons I cant just create a parent component and call it there and duplicate it four times, it needs to be done in this component if possible.
CodePudding user response:
Create an array with your data, and then use map
to print the divs:
const data = [
{
id: 'turtle-id',
title: 'I like turtles',
text: '...',
// rest of needed data
}, {
// ...
}
];
return (
data.map(item => {
return (
<div key={item.id} id={item.id}>
<h1>{item.title}</h1>
<p>{item.text}</p>
<button>Click me!</button>
</div>
);
});
);
CodePudding user response:
You can create an array of objects outside of component and loop through them. Something like this.
const animals = [{
id: "turtle-id",
title: "I like turtles!",
defineText: (value) => `there are ${value} turtles in my house!`
}, ....]
and then in your component's return, you can do something like this.
...
return (
<div>
{animals.map((animal) => {
return (
<div key={animal.id} id={animal.id}>
<h1>{animal.title}</h1>
<p>{animal.defineText(animalAmount.current)}</p>
<button>Click me!</button>
</div>
);
})}
</div>
);
...
CodePudding user response:
Have a set of data describing the animals and set your state with it.
Shift your animal containers into a new component (
Animal
).map
over the animals state to create a series of Animals.When a button is clicked update the count value of that animal.
const { useState } = React;
// Pass in some data
function Animals({ data }) {
// Initialise state with the data
const [ animals, setAnimals ] = useState(data);
// Copy the state, find the name of the
// animal we're updating the count for from
// the container's dataset, find the index of the
// animal object in state, update its count value
// and the update the state
function handleCount(e) {
const copy = [...animals];
const { name } = e.target.closest('.animal').dataset;
const index = copy.findIndex(obj => obj.name === name);
copy[index].count;
setAnimals(copy);
}
// `map` over the animals state
// an return an array of Animal components
return animals.map(animal => {
return (
<Animal
animal={animal}
handleCount={handleCount}
/>
);
});
}
// Animal component
function Animal({ animal, handleCount }) {
return (
<div className="animal" data-name={animal.name}>
<h1>I like {animal.plural}!</h1>
<p>There are {animal.count} {animal.plural} in my house!</p>
<button onClick={handleCount}>Click me!</button>
</div>
);
}
const data = [
{ name: 'turtle', plural: 'turtles', count: 0 },
{ name: 'dog', plural: 'dogs', count: 0 },
{ name: 'fish', plural: 'fish', count: 0 },
{ name: 'hippo', plural: 'hippos', count: 0 }
];
ReactDOM.render(
<Animals data={data} />,
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>