开发者问题收集

无效的钩子调用 - React Hooks

2020-11-28
456

我对 JS 和 React 还很陌生。当我尝试让一个组件出现并在单击另一个组件时消失时,我收到此错误: 无效的钩子调用 这是我的代码:

const RenderList = ({data}) => {
    return data.map((option, index) => {
        return <Item title={option}/>
    });
};

const Header = ({ title, style, press }) => (
    <TouchableHighlight onPress={press}>
        <Text  style={style} >{title}</Text>
    </TouchableHighlight>
)

const RenderItem = ( {item} ) => {
    console.log(styles)

    let dataToShow;
    
    const [listState, setListState] = useState(true);

    if (listState){
        dataToShow = <RenderList data={item.data}/>
    } else {
        dataToShow = <Text/>
    }

    return (
        <View style={styles.section}>
            <Header title={item.title} style={styles.header} press={setListState(!listState)}/>
            {dataToShow}
        </View>
)}

编辑 RenderItem 在平面列表元素中用作函数。(据我所知)

const SettingsSection = (props) => {
    const db = props.data;

    return(
        <View>
            <FlatList 
                style={styles.sectionList}
                data={db}
                renderItem={RenderItem}
                keyExtractor={item=>item.title}  
                ItemSeparatorComponent={FlatListItemSeparator}          
            />            
        </View>
    );
}
2个回答

renderItem ,顾名思义,是一个 render prop ,因此是直接调用的(例如: renderItem({item}) ),而不是实例化为组件(例如: <RenderItem item={item}/> )。

这意味着 React 没有为钩子创建适当的渲染“上下文”。您可以通过在渲染 prop 上像这样使用 RenderItem 函数来确保您的 RenderItem 函数被实例化为组件:

<FlatList 
    style={styles.sectionList}
    data={db}
    renderItem={item => <RenderItem {...item}/>} // see here!
    keyExtractor={item=>item.title}  
    ItemSeparatorComponent={FlatListItemSeparator}          
/>

这样, RenderItem 被视为组件,因此可以使用钩子。

Kroltan
2020-11-28

我认为问题是由于按下 setListState(!listState) 而发生的。我建议您将状态更改方法包装到函数中。因为 onPress 仅接受函数类型,但您为其提供了来自钩子的返回语句。

const RenderList = ({data}) => {
    return data.map((option, index) => {
        return <Item title={option}/>
    });
};

const Header = ({ title, style, press }) => (
    <TouchableHighlight onPress={press}>
        <Text  style={style} >{title}</Text>
    </TouchableHighlight>
)

const RenderItem = ( {item} ) => {
    console.log(styles)

    let dataToShow;
    
    const [listState, setListState] = useState(true);

    if (listState){
        dataToShow = <RenderList data={item.data}/>
    } else {
        dataToShow = <Text/>
    }

    return (
        <View style={styles.section}>
            <Header 
                   title={item.title} 
                   style={styles.header}
                   press={()=>{
                       setListState(!listState)
                   }}
             />
            {dataToShow}
        </View>
)}
cangokceaslan
2020-11-28