useState Hook 的 set 方法不会重新渲染使用过的 Hook [英] set method for useState Hook doesn't re-render used Hooks

查看:100
本文介绍了useState Hook 的 set 方法不会重新渲染使用过的 Hook的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用setFavorite"更新我的状态时,它会重新渲染我的组件而不是我的组件中使用的钩子.在这种情况下,当我更新状态时不会调用 React.useLayOutEffect,而是调用了 alert("test").

When I update my state using "setFavorite", it re-renders my Component but not the hooks, used in my component. In this case, React.useLayOutEffect isn't called when I update my state, but the alert("test") is called.

当我使用 expo 刷新时,它会重新渲染 useLayoutEffect Hook,并且一切正常.

When I refresh using expo, it re-renders the useLayoutEffect Hook and everything works fine.

你有什么解决办法吗?

const database = SQLite.openDatabase('favoriten.db');

export default function LokalDetailsScreen(props) {
const [lokal, setLokal] = React.useState(props.route.params.lokal);
const [favorit, setFavorit] = React.useState(false);
const [navigation, setNavigation] = React.useState(props.navigation);

React.useEffect(() => {
    database.transaction((transaction) =>
        transaction.executeSql(
            'CREATE TABLE IF NOT EXISTS favoriten (id INTEGER PRIMARY KEY NOT NULL, lokalID           TEXT)'
        )
    );
    _retrieveData(lokal.id, setFavorit);
});

alert('test');

let HeaderRight = () =>
    favorit ? (
        <MaterialIcons
            style={styles.icon}
            name={'favorite'}
            size={33}
            color={'red'}
            onPress={() => {
                _delFromDB(lokal.id, setFavorit);
            }}
        />
    ) : (
        <MaterialIcons
            style={styles.icon}
            name={'favorite-border'}
            size={33}
            color={'red'}
            onPress={() => {
                _saveToDB(lokal.id, setFavorit);
            }}
        />
    );

React.useLayoutEffect(() => {
    alert('re-render with: ' + favorit);
    navigation.setOptions({
        headerRight: () => <HeaderRight />,
    });
}, [navigation]);

return (
    <ScrollView style={styles.scrollView} contentContainerStyle={styles.container}>
        <View style={styles.large}>
            <Image style={styles.image} source={{ uri: lokal.titelbildURL }} />
            <Text>{lokal.name}</Text>
            <Text>{`Favorit: ${favorit}`}</Text>
        </View>
    </ScrollView>
);
}

function _saveToDB(id, setFavorit) {
database.transaction((transaction) => {
    transaction.executeSql('INSERT INTO favoriten (lokalID) VALUES (?)', [id], (_, result)     => {
        if (result.rowsAffected > 0) {
            console.log('zu Favs hinzugefügt:' + ' ' + result.rowsAffected);
            setFavorit(true);
        }
    });
});
}

function _delFromDB(id, setFavorit) {
database.transaction((transaction) =>
    transaction.executeSql('DELETE FROM favoriten WHERE lokalID = ?', [id], (_, result) => {
        if (result.rowsAffected > 0) {
            console.log('von Favs entfernt:' + result.rowsAffected);
            setFavorit(false);
        } else {
            console.log('nicht von Favs entfernt:' + result.rowsAffected);
            setFavorit(true);
        }
    })
);
}

function _retrieveData(id, setFavorit) {
var res = false;
database.transaction((transaction) =>
    transaction.executeSql('SELECT * FROM favoriten WHERE lokalID = ?', [id], (_, result) =>     {
        console.log('Zeilen mit diesem Lokal: ' + result.rows.length);
        if (result.rows.length > 0) {
            console.log('fav auf true gesetzt');
            setFavorit(true);
        } else {
            console.log('fav auf false gesetzt');
            setFavorit(false);
        }
    })
);
}

一些 Lorem ipsum dolor sat amet、consetetur sadipscing elitr、sed diam nonumy eirmod tempor invidunt ut laboure et dolore magna aliquyam erat、sed diam voluptua.在 vero eos et accusam et justo duo dolores et ea rebum.Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sat amet.

Some Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

推荐答案

useEffectuseLayoutEffect 钩子获取依赖状态的第二个参数,用于评估是否钩子必须重新运行.

The useEffect and useLayoutEffect hooks get a second parameter of dependent state which will be used to evaluate if the hook has to rerun.

useEffect(callback, dependencies)

useLayoutEffect(callback, dependencies)

参见:https://reactjs.org/docs/hooks-reference.html#uselayouteffect

因此,在您的示例中,请确保 favorit 包含在 useLayoutEffect 的依赖项列表中:

So in your example make sure that favorit is included in the list of dependencies of the useLayoutEffect:

React.useLayoutEffect(() => {
    alert('re-render with: ' + favorit);
    navigation.setOptions({
        headerRight: () => <HeaderRight />,
    });
}, [navigation, favorit]);

这篇关于useState Hook 的 set 方法不会重新渲染使用过的 Hook的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆