[英]react native rendering a list of buttons can't figure out what's wrong
I'm trying to make a list of buttons based on the input from user input type is an array of options like so multipleOptions = ['1', '2', '3']
then we loop through each option to show a Button can't figure out why it's not working here's my code:我正在尝试根据用户输入类型的输入创建一个按钮列表,它是一个选项数组,例如
multipleOptions = ['1', '2', '3']
然后我们遍历每个选项以显示一个 Button无法弄清楚为什么它不起作用这是我的代码:
import React, { useState } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const InputButton = (multipleOptions, likertScale, onPress) => {
const [options, setOptions] = useState([]);
if (likertScale) {
setOptions([...new Array(likertScale).keys()].map((i) => i));
} else if (multipleOptions) setOptions(multipleOptions);
return (
<View style={styles.container}>
{options ? (
options.map((option, i) => (
<View style={[styles.button]} key={`${i}`}>
<TouchableOpacity onPress={() => onPress(option)}>
<Text>{option}</Text>
</TouchableOpacity>
</View>
))
) : (
<Text>no options</Text>
)}
</View>
);
};
const App = () => {
return (
<View>
<InputButton multipleOptions={['1', '2','3']} />
</View>
)
}
const styles = StyleSheet.create({})
export default App;
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
},
button: {
margin: 3,
flex: 1,
backgroundColor: '#EEF6FA',
minHeight: 72,
borderRadius: 2,
justifyContent: 'center',
alignItems: 'center',
},
});
the error message is错误信息是
Too many re-renders. React limits the number of renders to prevent an infinite loop.
or sometimes this或者有时这个
options.map is not a function
TypeError: options.map is not a function
at InputButton
(All kind of optimisations are welcome) Thanks in Advance guys. (欢迎各种优化)提前谢谢大家。
code demo https://snack.expo.io/@mansouriala/dac832代码演示https://snack.expo.io/@mansouriala/dac832
You have several issues here.你在这里有几个问题。
The first, which leads to Too many re-renders. React limits the number of renders to prevent an infinite loop.
第一个,这导致了
Too many re-renders. React limits the number of renders to prevent an infinite loop.
Too many re-renders. React limits the number of renders to prevent an infinite loop.
is because you're calling setOptions
at each render, which triggers another render, etc… This is infinite loop, because when you're setting a state, React re-renders the component.是因为您在每次渲染时调用
setOptions
,这会触发另一个渲染,等等……这是无限循环,因为当您设置 state 时,React 会重新渲染组件。 To avoid that, you have to wrap your expression with useEffect
and the correct dependencies.为避免这种情况,您必须使用
useEffect
和正确的依赖项来包装您的表达式。
React.useEffect(() => {
if (likertScale) {
setOptions([...new Array(likertScale).keys()].map((i) => i));
} else if (multipleOptions) {
setOptions(multipleOptions);
}, [multipleOptions, likertScale]);
This way, this expression would only run when multipleOptions
or likertScale
change.这样,这个表达式只会在
multipleOptions
或likertScale
改变时运行。 https://reactjs.org/docs/hooks-reference.html#useeffect https://reactjs.org/docs/hooks-reference.html#useeffect
The other problem is that InputButton
props argument is wrong: you forgot the props destructuring.另一个问题是
InputButton
道具参数是错误的:你忘记了道具解构。 It should be const InputButton = ({ multipleOptions, likertScale, onPress }) => { /* body function */ }
.它应该是
const InputButton = ({ multipleOptions, likertScale, onPress }) => { /* body function */ }
。
Finally, it's a bad practice to use an array index as a key
prop, because array order could change.最后,使用数组索引作为
key
prop 是一种不好的做法,因为数组顺序可能会改变。 You should use a stable key, like the option value key={option}
.您应该使用稳定的密钥,例如选项值
key={option}
。
https://reactjs.org/docs/lists-and-keys.html#keys https://reactjs.org/docs/lists-and-keys.html#keys
You put set state in every re-render so you get a loop.你在每次重新渲染中都设置了 state ,这样你就得到了一个循环。 So you have two options use useEffect to just set state one time or set the first state directly.
因此,您有两个选项使用 useEffect 来设置一次 state 或直接设置第一个 state。 https://snack.expo.io/ZvLQM9FEF
https://snack.expo.io/ZvLQM9FEF
const InputButton = ({multipleOptions, likertScale, onPress}) => {
const [options, setOptions] = useState(likertScale?[...new Array(likertScale).keys()].map((i) => i):[ ...multipleOptions]);
return (
<View style={styles.container}>
{options ? (
options.map((option, i) => (
<View style={[styles.button]} key={`${i}`}>
<TouchableOpacity onPress={() => onPress(option)}>
<Text>{option}</Text>
</TouchableOpacity>
</View>
))
) : (
<Text>no options</Text>
)}
</View>
);
};
export default InputButton;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.