Передать функцию, ссылающуюся на другую функцию, в дочерний компонент в React

В моем приложении основной компонент определяет функцию, которая имеет ссылку на локальную функцию, например:

class Root extends React.Component {
     constructor(props) {
        super(props);
     }

    tokenizer({email, password}) {
        return this.props.client.query({
            query: getToken,
            variables: {email: email, password: password}
        }).then(response => {
            return response.data
        }).catch(error => {
            console.warn(error);
            return {}
        });
    }

    async fetchToken({email, password}) {
        const data = await this.tokenizer({email, password});
        this.props.updateToken({token: data.login});//redux dispatch to props
    }

    render() {
        if (this.props.token) {
            return (
                <Home />
            )
        } else {
            return <Login fetchToken = {this.fetchToken} />;
        }
    }
}

Дочерний компонент (а именно Login) будет использовать функцию fetchToken следующим образом:

class Login extends Component {
    constructor(props) {
        super(props);
        this.state = {
            email: '',
            password: ''
        };
        this.handleChangeEvent = this.handleChangeEvent.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChangeEvent(event) {
        this.setState({[event.target.name]: event.target.value});
    }

    handleSubmit(event) {
        event.preventDefault();
        this.props.fetchToken(this.state);
    }

    render() {
        return (
            <Form onSubmit = {this.handleSubmit}>
                   // ... Form HTML here
            </Form>
        )
    }
}

Теперь, когда форма отправлена, fetchToken не может ссылаться на this.tokenizer из-за следующей ошибки: Uncaught (in promise) TypeError: this.tokenizer is not a function

Я мог бы передать метод tokenizer, но он, в свою очередь, ссылается на другие реквизиты. Таким образом, мне пришлось бы передать любую функцию/состояние/реквизит, связанную с этим, что кажется излишним. Вместо этого можно было бы вызывать fetchToken только сославшись на него в родительском элементе?

Можно ли привязать функции токенизатора, fetchToken? tokenizer = ({email, password}) => { и await fetchToken = () =>

Avanthika 07.03.2019 12:13
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
92
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы должны связать все свои методы, если хотите использовать их в одном контексте. Самый простой способ сделать это — использовать функцию стрелки в вашем классе для каждого метода.

class Root extends React.Component {

    tokenizer = async ({email, password}) => {
        return this.props.client.query({
            query: getToken,
            variables: {email: email, password: password}
        }).then(response => {
            return response.data
        }).catch(error => {
            console.warn(error);
            return {}
        });
    }

    fetchToken = async ({email, password}) => {
        const data = await this.tokenizer({email, password});
        this.props.updateToken({token: data.login});//redux dispatch to props
    }

    render() {
        if (this.props.token) {
            return (
                <Home />
            )
        } else {
            return <Login fetchToken = {this.fetchToken} />;
        }
    }
}

Не уверен, как я пропустил это. Я связал функцию через конструктор как таковой this.fetchToken = this.fetchToken.bind(this);

Khaled 07.03.2019 12:18

fetchToken не имеет ссылки на this, поэтому вам нужно либо привязать его, либо использовать функцию стрелки. Чтобы привязать его, вы должны привязать его к this, как вы делаете это с handleChangeEvent и handleSubmit в конструкторе вашего компонента входа в систему.

В качестве стрелочной функции ваш fetchToken будет выглядеть так:

async fetchToken = ({email, password}) => {
    const data = await this.tokenizer({email, password});
    this.props.updateToken({token: data.login});//redux dispatch to props
}

Я предлагаю сделать то же самое с токенизатором.

Как показывает ошибка, при выполнении этой строки кода возникает ошибка типа:

const data = await this.tokenizer({email, password});

вы вызываете функцию tokenizer с помощью this, но на самом деле this теперь не указывает на тот же объект. если вы console.info(this.tokenizer) это даст вам undefined. Да! вы улавливаете проблему, проблема заключается в масштабе. позвольте мне немного объяснить вам область применения this:

Когда она находится внутри метода объекта, владельцем функции является объект. Таким образом, ключевое слово this привязано к объекту.

Тем не менее, когда он находится внутри функции, отдельной функции или внутри другой функции, this всегда будет относиться к глобальной области видимости.

Это известно как причуда JavaScript, означающее что-то, что просто происходит в JavaScript, что не совсем просто и работает не так, как вы думаете. Это также было расценено разработчиками как плохой выбор дизайна, который они теперь исправляют с помощью стрелочных функций ES6.

Вы можете либо привязать свой метод, который разработчики использовали до ES6, либо теперь вы можете просто использовать функцию стрелки. вот так

async fetchToken = ({email, password}) => {
    const data = await this.tokenizer({email, password});
    this.props.updateToken({token: data.login});//redux dispatch to props
}

Точно так же вы можете сделать функцию токенизатора также функцией стрелки.

Другие вопросы по теме