I am making a character creation screen in react and am setting up TouchableOpacity clickables that the user can click on to change the look of their character in the window. The default character displayed is a plain character before the clickables add items of clothing to them.
Currently, I am receiving an error saying that "choice" is undefined when the image is meant to be displayed. Here's the relevant code I have so far:
export default function App() {
const red = require('./assets/dummyRed.png');
const blue = require('./assets/dummyBlue.png');
const yellow = require('./assets/dummyYellow.png');
const normal = require('./assets/dummy.png');
const colours = { red, blue, yellow, normal }
const character = () => {const [choice, setSelected] = useState(colours.normal)}
return (
<View style={styles.wrap}>
<View style= {{alignItems : 'center'}}>
<View style={styles.characterWrap}>
<img src = {choice} alt = 'colours' />
</View>
</View>
<View style={{flexDirection:'row', alignItems:'stretch'}}>
<TouchableOpacity onPress= { () => setSelected(colours.yellow) } style={styles.choiceWrap}>
<Image source={yellow} style={{ width: 100, height: 100 }} />
</TouchableOpacity>
</View>
</View>
</View>
);
}
I have taken away some buttons so that I can just test with the yellow option, but the default never shows. Is there anything that I'm obviously doing wrong? I'm a bit new to React in general and this is throwing me for a loop.
CodePudding user response:
You should declare your useStates on top of the function. Look below this what you should do. Before the useState was inside the scope of the character()
function and couldn't be accessed in the App()
function scope.
Heres a great article on rules for react hooks. One of the rules is Only call Hooks at the top level (https://blog.bitsrc.io/best-practices-with-react-hooks-69d7e4af69a7)
export default function App() {
const red = require('./assets/dummyRed.png');
const blue = require('./assets/dummyBlue.png');
const yellow = require('./assets/dummyYellow.png');
const normal = require('./assets/dummy.png');
// Do this
const [choice, setSelected] = useState(colours.normal)
const colours = { red, blue, yellow, normal }
return (
<View style={styles.wrap}>
<View style= {{alignItems : 'center'}}>
<View style={styles.characterWrap}>
<img src = {choice} alt = 'colours' />
</View>
</View>
<View style={{flexDirection:'row', alignItems:'stretch'}}>
<TouchableOpacity onPress= { () => setSelected(colours.yellow) } style={styles.choiceWrap}>
<Image source={yellow} style={{ width: 100, height: 100 }} />
</TouchableOpacity>
</View>
</View>
</View>
);
}