我正试图根据用户输入创建一个按钮列表输入类型是一个选项数组,如multipleOptions = ['1', '2', '3']
然后我们循环通过每个选项来显示一个按钮无法找出为什么它不工作这是我的代码:
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',
},
});
错误信息是
Too many re-renders. React limits the number of renders to prevent an infinite loop.
或者有时是
options.map is not a function
TypeError: options.map is not a function
at InputButton
(欢迎各种优化)提前感谢各位。
代码演示https://snack.expo.io/@mansouriala/dac832
你在每次重新渲染中设置状态,这样你就得到了一个循环。你有两个选择使用useEffect来一次设置状态或者直接设置第一个状态。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;
你有几个问题。
首先,导致Too many re-renders. React limits the number of renders to prevent an infinite loop.
是因为你在每次渲染时调用setOptions
,这会触发另一次渲染,等等…这是无限循环,因为当你设置状态时,React会重新渲染组件。为了避免这种情况,您必须用useEffect
和正确的依赖关系包装表达式。
React.useEffect(() => {
if (likertScale) {
setOptions([...new Array(likertScale).keys()].map((i) => i));
} else if (multipleOptions) {
setOptions(multipleOptions);
}, [multipleOptions, likertScale]);
这样,这个表达式只会在multipleOptions
或likertScale
发生变化时运行。https://reactjs.org/docs/hooks-reference.html useeffect
另一个问题是InputButton
props参数是错误的:您忘记了props的解构。应该是const InputButton = ({ multipleOptions, likertScale, onPress }) => { /* body function */ }
。
最后,使用数组索引作为key
prop是一个不好的做法,因为数组顺序可能会改变。您应该使用一个稳定的键,如选项值key={option}
。
https://reactjs.org/docs/lists-and-keys.html
#键