I'm trying to make a React app, now I have a select input box with some Pokémon in it, what I need to do is whenever the selection changes (i.e. the Pokémon changes) the Pokémon sprite will Make a small shaking animation. Currently I just have a sprite that changes and an audio that plays when the selection value changes. How can I implement this functionality? I've tried using
Select.ts
:
import { closest } from "fastest-levenshtein"; import React, { useState } from "react"; import { cries, pokemons } from "../data"; import styled from "styled-components"; import { Img, ani } from "../styles"; function Select() { const [src, setSrc] = useState(require("../data/sprites/bulbasaur.png")); const opts: { label: string; value: string }[] = []; for (let i = 0; i < pokemons.length; i++) { opts.push({ label: pokemons[i][0].toUpperCase() + pokemons[i].slice(1), value: pokemons[i], }); } return ( <div> <div> <select onChange={(evt) => { setSrc(require(`../data/sprites/${evt.target.value}.png`)); const str = closest(evt.target.value, cries); const res = new Audio(require(`../data/cries/${str}`)); res.volume = 0.2; res.play(); styled(Img)` margin-left: 2.5em; animation: ${ani}; `; }} > {opts.map(({ label, value }) => ( <option key={value} label={label} value={value}></option> ))} </select> </div> <Img src={src} alt="" className="sprite" /> </div> ); } export default Select;
img.styled.ts
:
import styled, { css } from "styled-components"; import { shake } from "./shake.stiled"; const ani = css(["", " 0.3s linear"] as any as TemplateStringsArray, shake); const Img = styled.img` margin-left: 2.5em; animation: ${ani}; `; export { Img, ani };
Thanks!
P粉9905682832024-04-02 00:10:18
I believe that putting the src state in the parent component, by passing setSrc as prop to that component, instead of declaring the src state in this component, will help you. So in this component, onChange={() => setSrc(newVal)}
, where setSrc is passed to the Select component as prop.
Alternatively, I recommend storing evt.target.value as a state and updating the value in the onChange event.
const [chosenImg, setChosenImg] = useState() const [src, setSrc] = useState(require("../data/sprites/bulbasaur.png")); useEffect(() => { setSrc(require(`../data/sprites/${chosenImg}.png`)) }, [chosenImg]);
Then:
onChange={()=> setChosenImg(evt.target.value)}