Reputation: 69
I am learning react by coding a gamertag generator. It generates random tags and keeps a list, and each can be rated. My main app is a functional component utilizing the useState hook to set state: an array of objects with details about the tags, namely a star rating system.
I generate each gamertag using a react component Tag, within, it uses a functional component, RenderStars to draw the stars. Each tag stars off with 0 stars, so 5 empty stars, and I want the user to change rating by clicking on however many stars, 1-5. RenderStars will then draw however many empty and filled stars as needed.
I have a function in App, changeStars, that I can't seem to get any of the child components to call successfully. I am passing the function to the child components through props.
I've tried writing changeStars in arrow notation and as a plain function. I've tried it without requiring any parameters. I've tried calling it within Tag just using a button. There's other ways I've messed with it that I can't quite recall, just messing with the syntax and trying other things from stackexchange and articles.
I don't bind the function because it's created in a functional component.
This seems like a super basic task and I can't figure it out. Yes i've read the Docs from react.js
Here is some of the code, I'll try to take out as much as possible:
function App() {
const [tagInventory, setTagInventory] = useState([]);
const latestTag = tagInventory[tagInventory.length - 1] ? tagInventory[tagInventory.length -1] : null;
const handleAdd = (tag) => {
uses hook to add tag to state
}
const makeTag = () => {
creates random tag
}
function changeStars(stars,key) {
console.log(stars, key);
//this will change the star rating of an individual tag
}
return (
<main>
A bunch of amazing interface html
<section className="tagInventory">
{tagInventory.map( (item) =>
<Tag
key={item.timeStamp}
tagItem={item}
/>
) }
</section>
</main>
);
};
class Tag extends React.Component {
render() {
const item = this.props.tagItem;
const stars = this.props.tagItem.stars;
const key = this.props.tagItem.timeStamp;
const tagClass = this.props.newTag ? "tag-item new-item" : "tag-item";
return (
<div className={tagClass}>
code to generate cool tag info
</div>
<RenderStars
stars={stars}
changeStars={changeStars}
newTag={false}
key={key}
/>
</div>
);
}
}
const RenderStars = (props) => {
// ref for using symbol tag https://css-tricks.com/svg-symbol-good-choice-icons/
return (
i load svg of stars then can display as many as i need later...
now i draw 4 stars, for the example i'll stop at the first, here's the call..
{props.stars === 0 &&
<div>
<svg className="empty-star" onClick={() => props.changeStars(4,props.key)}>
<use xlinkHref="#empty-star" />
now the other stars and whatnot
}
Thanks!
Upvotes: 0
Views: 1939
Reputation: 56
So basically you want to pass the function changeStars
from App to Tag and then to RenderStars, is that correct?
If so, you're forgetting to pass it from App to Tag
App:
<section className="tagInventory">
{tagInventory.map( (item) =>
<Tag
key={item.timeStamp}
tagItem={item}
/>
) }
</section>
Should be passing the function:
<section className="tagInventory">
{tagInventory.map( (item) =>
<Tag
key={item.timeStamp}
tagItem={item}
changeStars={changeStars}
/>
) }
</section>
And then on Tag:
const changeStars = this.props.changeStars;
Upvotes: 1