Использование того же имени переменной в состоянии компонента и реквизита с избыточным, и я получаю ошибку неопределенного реквизита - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть компоненты, которые должны знать, зарегистрирован ли пользователь с Facebook или нет, поэтому я использую функцию от mapStateToProps до сопоставления состояния редукции с реквизитами компонентов .
В то же время некоторые компоненты могут входить в систему самостоятельно, поэтому им необходим локальный state, чтобы знать, зарегистрирован ли пользователь или нет (я не могу обновить реквизиты компонента внутри самого компонента).

Когда пользователь входит в систему, он отправляет событие loggedIn.

Это лучшая практика или я что-то не так делаю?У меня есть такие компоненты:

import ...

const FBSDK = require('react-native-fbsdk');
const {
    LoginButton,
    AccessToken,
    LoginManager
} = FBSDK;

class Settings extends Component {

    constructor(props) {
        super(props);

        this.state = {
            isLoggedIn: false,
        };
    }

    componentDidMount () {
        this._loadInitialState();
    }

    async _loadInitialState() {
        AccessToken.getCurrentAccessToken().then(
            (data) => {
                if (data) {
                    this.setState({
                        isLoggedIn: true,
                    });

                    // Dispatch loggedIn action
                    this.props.loggedIn();
                }
            }
        );
    }

    render() {
        const {navigate} = this.props.navigation;

        return (
            <Content>
                <List style={styles.list}>
                    {this.state.isLoggedIn &&
                        <ListItem>
                            <Body>
                                ...
                            </Body>
                        </ListItem>
                    }
                    <ListItem style={styles.listItem}>
                        <LoginButton
                            readPermissions={["user_friends", "email"]}
                            onLoginFinished={
                                (error, result) => {
                                    if (error) {
                                        alert("login has error: " + result.error);
                                    } else if (result.isCancelled) {
                                        alert("login is cancelled.");
                                    } else {
                                        AccessToken.getCurrentAccessToken().then(
                                            (data) => {                                                                                                       this.setState({isLoggedIn: true});

                                                // Dispatch loggedIn action
                                                this.props.loggedIn();
                                            }
                                        ).catch(function(e) {
                                            log(e); // "oh, no!"
                                        });
                                    }
                                }
                            }
                            onLogoutFinished={() => {
                                this.setState({isLoggedIn: false});

                                // Dispatch loggedOut action
                                this.props.loggedOut();
                            }} />
                    </ListItem>
                </List>
            </Content>
        )
    }
}

Settings.propTypes = {
    isLoggedIn: PropTypes.bool.isRequired,
}

const mapStateToProps = (state) => {
    return {
        isLoggedIn: state.isLoggedIn,
    };
};

const mapDispatchToProps = (dispatch) => ({
    startup: () => dispatch(StartupActions.startup()),
    loggedIn: () => dispatch({
        type: LOGGED_IN
    }),
    loggedOut: () => dispatch({
        type: LOGGED_OUT
    })
});

export default connect(mapStateToProps, mapDispatchToProps, null, {pure: false})(Settings);

Как видите, компонент имеет isLoggedIn локальное состояние и isLoggedIn проп, и мне нужно обновить оба одновременно.

Я спрашиваю причину, отличную от практики, когда я вхожу в систему с пользователем Facebook Я получаю эту ошибку (я не искал где, но кажется, что где-то props не определены):

TypeError: Cannot read property 'loggedIn' of undefined

и я не знаю, где и почему это происходит и зависит ли это от этого кода.

1 Ответ

0 голосов
/ 19 сентября 2018

Вам необходимо привязать свой метод для доступа к this в _loadInitialState методе.

Самый простой способ - использовать функцию стрелки как

 _loadInitialState = async() => {

Также отправляйте действия, когда setState завершит обновление в методе обратного вызова

this.setState({
    isLoggedIn: true,
 }, () => this.props.loggedIn()); 

onLogoutFinished={() => {
   this.setState({isLoggedIn: false}, () => this.props.loggedOut());
}}
...