Подтвердить что ты не робот

Внедрить логин Facebook API с помощью reactjs

Я работаю над использованием Javascript SDK для проверки подлинности. Я смог правильно импортировать SDK и поместил на моей странице кнопку Like. Но кнопка входа в facebook должна быть завернута в тег:

<fb:login-button/>

В настоящее время у меня есть весь код из Facebook Login tutorial, вставленный в мой index.html, единственный html файл в моем проекте, в котором размещается приложение React. Но мне нужно поставить последнюю часть, которая имеет действительную кнопку входа, в мой компонент React. Когда я попытался это сделать, я получил следующую ошибку:

ReactifyError: /Users/ritmatter/reps/js/components/Signup.jsx: Parse Error: Line 82: Unexpected end of input while parsing file: /Users/ritmatter/reps/js/components/Signup.jsx
sdk.js:61 The "fb-root" div has not been created, auto-creating
ping?client_id=894010190618709&domain=localhost&origin=1&redirect_uri=http%3A%2F%2Fstatic.ak.facebo…:1 Given URL is not allowed by the Application configuration.: One or more of the given URLs is not allowed by the App settings.  It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App domains.

Как я могу заставить кнопку входа в систему реагировать?

4b9b3361

Ответ 1

Я выяснил, как изменить учебник Facebook для API входа с помощью ReactJS. Надеюсь, это поможет кому-то еще бороться с этим.

Во-первых, в компоненте реакции, в котором вы хотите использовать ссылку "Вход", укажите этот код:

componentDidMount: function() {
  window.fbAsyncInit = function() {
    FB.init({
      appId      : '<YOUR_APP_ID>',
      cookie     : true,  // enable cookies to allow the server to access
                        // the session
      xfbml      : true,  // parse social plugins on this page
      version    : 'v2.1' // use version 2.1
    });

    // Now that we've initialized the JavaScript SDK, we call
    // FB.getLoginStatus().  This function gets the state of the
    // person visiting this page and can return one of three states to
    // the callback you provide.  They can be:
    //
    // 1. Logged into your app ('connected')
    // 2. Logged into Facebook, but not your app ('not_authorized')
    // 3. Not logged into Facebook and can't tell if they are logged into
    //    your app or not.
    //
    // These three cases are handled in the callback function.
    FB.getLoginStatus(function(response) {
      this.statusChangeCallback(response);
    }.bind(this));
  }.bind(this);

  // Load the SDK asynchronously
  (function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'facebook-jssdk'));
},

// Here we run a very simple test of the Graph API after login is
// successful.  See statusChangeCallback() for when this call is made.
testAPI: function() {
  console.log('Welcome!  Fetching your information.... ');
  FB.api('/me', function(response) {
  console.log('Successful login for: ' + response.name);
  document.getElementById('status').innerHTML =
    'Thanks for logging in, ' + response.name + '!';
  });
},

// This is called with the results from from FB.getLoginStatus().
statusChangeCallback: function(response) {
  console.log('statusChangeCallback');
  console.log(response);
  // The response object is returned with a status field that lets the
  // app know the current login status of the person.
  // Full docs on the response object can be found in the documentation
  // for FB.getLoginStatus().
  if (response.status === 'connected') {
    // Logged into your app and Facebook.
    this.testAPI();
  } else if (response.status === 'not_authorized') {
    // The person is logged into Facebook, but not your app.
    document.getElementById('status').innerHTML = 'Please log ' +
      'into this app.';
  } else {
    // The person is not logged into Facebook, so we're not sure if
    // they are logged into this app or not.
    document.getElementById('status').innerHTML = 'Please log ' +
    'into Facebook.';
  }
},

// This function is called when someone finishes with the Login
// Button.  See the onlogin handler attached to it in the sample
// code below.
checkLoginState: function() {
  FB.getLoginStatus(function(response) {
    this.statusChangeCallback(response);
  }.bind(this));
},

handleClick: function() {
  FB.login(this.checkLoginState());
},

Затем в вашем методе рендеринга убедитесь, что у вас есть HTML-код, который вызовет этот handleClick:

<a href="#" onClick={this.handleClick}>Login</a>

Обратите внимание: это тот же код из учебника, но он помещается в компонент ReactJS. Единственное различие заключается в том, что вам необходимо связать это стратегически, чтобы функции API Facebook были частью вашего реагирующего компонента. Этот логин завершится с ответом, полученным от ответа, предоставленного FB.getLoginStatus(). Вы также можете извлечь токен из этого объекта ответа и отправить его на свой сервер для аутентификации с помощью passport-facebook-token.

Ответ 2

Я использовал Promises для потока Facebook Auth

Mixins/facebook.js

const promises = {
    init: () => {
        return new Promise((resolve, reject) => {
            if (typeof FB !== 'undefined') {
                resolve();
            } else {
                window.fbAsyncInit = () => {
                    FB.init({
                        appId      : '<app_id>',
                        cookie     : true, 
                        xfbml      : true,  
                        version    : 'v2.5'
                    });
                    resolve();
                };
                (function(d, s, id) {
                    var js, fjs = d.getElementsByTagName(s)[0];
                    if (d.getElementById(id)) return;
                    js = d.createElement(s); js.id = id;
                    js.src = "//connect.facebook.net/en_US/sdk.js";
                    fjs.parentNode.insertBefore(js, fjs);
                }(document, 'script', 'facebook-jssdk'));
            }
        });
    },
    checkLoginState: () => {
        return new Promise((resolve, reject) => {
            FB.getLoginStatus((response) => {
                response.status === 'connected' ? resolve(response) : reject(response);
            });
        });
    },
    login: () => {
        return new Promise((resolve, reject) => {
            FB.login((response) => {
                response.status === 'connected' ? resolve(response) : reject(response);
            });
        });
    },
    logout: () => {
        return new Promise((resolve, reject) => {
            FB.logout((response) => {
                response.authResponse ? resolve(response) : reject(response);
            });
        });
    },
    fetch: () => {
        return new Promise((resolve, reject) => {
            FB.api(
                '/me', 
                {fields: 'first_name, last_name, gender'},
                response => response.error ? reject(response) : resolve(response)
            );
        });
    }
}

export const Facebook = {
    doLogin() {
        this.setState({
            loading: true
        }, () => {
            promises.init()
                .then(
                    promises.checkLoginState,
                    error => { throw error; }
                )
                .then(
                    response => { this.setState({status: response.status}); },
                    promises.login
                )
                .then(
                    promises.fetch,
                    error => { throw error; }
                )
                .then(
                    response => { this.setState({loading: false, data: response, status: 'connected'}); },
                    error => { throw error; }
                )
                .catch((error) => { 
                    this.setState({loading: false, data: {}, status: 'unknown'});
                    console.warn(error); 
                });
        });
    },
    doLogout() {
        this.setState({
            loading: true
        }, () => {
            promises.init()
                .then(
                    promises.checkLoginState,
                    error => { throw error; }
                )
                .then(
                    promises.logout,
                    error => { this.setState({data: {}, status: 'unknown'}); }
                )
                .then(
                    response => { this.setState({loading: false, data: {}, status: 'unknown'}); },
                    error => { throw error; }
                )
                .catch(error => { 
                    this.setState({loading: false, data: {}, status: 'unknown'});
                    console.warn(error); 
                });
        });
    },
    checkStatus() {
        this.setState({
            loading: true
        }, () => {
            promises.init()
                .then(
                    promises.checkLoginState,
                    error => { throw error; }
                )
                .then(
                    response => { this.setState({status: response.status}); },
                    error => { throw error; }
                )
                .then(
                    promises.fetchUser,
                    error => { throw error; }
                )
                .then(
                    response => { this.setState({loading: false, data: response, status: 'connected'}); },
                    error => { throw error; }
                )
                .catch((error) => { 
                    this.setState({loading: false, data: {}, status: 'unknown'});
                    console.warn(error); 
                });
        });
    }
};

Profile.jsx

import {Facebook} from './mixins/Facebook.js';
import {Button} from 'react-bootstrap';

const ProfileHandler = React.createClass({
    mixins: [Facebook],
    componentDidMount() {
        this.checkStatus();
    },
    getInitialState() {
        return {
            status: 'unknown',
            loading: false,
            data: {}
        };
    },
    render() {
        const loading = this.state.loading ? <p>Please wait, profile is loading ...</p> : null;
        const message = this.state.status === 'connected'
            ? (<div>
                Hi {data.name}!
                <Button onClick={this.doLogout}>Logout</Button>
              </div>)
            : (<Button onClick={this.doLogin}>Login</Button>);
        return (
            <div>
                {message}
                {loading}
            </div>
        );
    }
});

Ответ 3

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

<div class="fb-login-button" onlogin="checkLoginState" data-size="medium" data-show-faces="false" data-auto-logout-link="false"></div>

Кнопка имеет атрибут onlogin, который не поддерживает парсер jsx. Использование data-onlogin в режиме реакции не работает, поэтому я просто добавил кнопку в componentDidMount:

        componentWillMount: function () {
                window['statusChangeCallback'] = this.statusChangeCallback;
                window['checkLoginState'] = this.checkLoginState;
        },
        componentDidMount: function () {
            var s = '<div class="fb-login-button" ' +
                'data-scope="public_profile,email" data-size="large" ' +
                'data-show-faces="false" data-auto-logout-link="true" ' +
                'onlogin="checkLoginState"></div>';

            var div = document.getElementById('social-login-button-facebook')
            div.innerHTML = s;
        },
        componentWillUnmount: function () {
            delete window['statusChangeCallback'];
            delete window['checkLoginState'];
        },
        statusChangeCallback: function(response) {
           console.log(response);
        },
        // Callback for Facebook login button
        checkLoginState: function() {
            console.log('checking login state...');
            FB.getLoginStatus(function(response) {
               statusChangeCallback(response);
            });
        },
        render: function() {

            return (
                <div id='social-login-button-facebook'>

                </div>
            );
        }

Все, что осталось сделать, это вызвать кнопку при установке компонента, если вы хотите автоматически вызвать checkLoginState.

Ответ 4

Это решение, которое я использовал для получения обратного вызова для входа. Вы можете добавить этот код для своей учетной записи Facebook в свой метод рендеринга:

<div className="fb-login-button" data-max-row="5" 
     data-size="large" 
     data-show-faces="false" 
     data-auto-logout-link="false" 
     href="javascript:void(0)">Login</div>

В своем коде добавьте следующие строки:

componentDidMount: function() {
    // facebook signin  button render
    window.fbAsyncInit = function() {
      FB.init({
        appId      : 'replace with your app id here',
        cookie     : true,  // enable cookies to allow the server to access
        // the session
        xfbml      : true,  // parse social plugins on this page
        version    : 'v2.1' // use version 2.1
      });

      // login callback implementation goes inside the function() { ... } block
      FB.Event.subscribe('auth.statusChange', function(response) {
        // example implementation
        if (response.authResponse) {
          console.log('Welcome!  Fetching your information.... ');
          FB.api('/me', function(response) {
            console.log('Good to see you, ' + response.name + '.');
          });
        } else {
          console.log('User cancelled login or did not fully authorize.');
        }
      });
    }.bind(this);

    // Load the SDK asynchronously
    (function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/en_US/sdk.js";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
  }
}

Вызов FB.Event.subscribe('auth.statusChange', callback_function) во время инициализации компонента важен, поскольку это в основном ваш обратный вызов входа. Оформить заказ здесь для FB.Event документации.

Ответ 6

Я размещаю свое решение здесь, так как ответы помогли мне реализовать его, но принятый ответ от ritmatter не работал без

FB.Event.subscribe('auth.statusChange', function(response)

из ответа RubyFanatic. Кроме того, "онлогин" меня очень смутил. Это просто не требуется в моих глазах.

Я хочу поделиться им, так как это решение c & p, здесь мой полный код против fb api v2.8 (реакция-бутстрап может быть выбита, конечно):

/* global FB*/
import React, { Component } from 'react';
import { Grid, Row, Col } from 'react-bootstrap';

export default class Login extends Component {
  constructor(props) {
    super(props);
    this.checkLoginState = this.checkLoginState.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.testAPI = this.testAPI.bind(this);
    this.statusChangeCallback = this.statusChangeCallback.bind(this);
  }

  componentDidMount() {
    window.fbAsyncInit = function() {
      FB.init({
        appId      : 'YOURAPIKEYHERE',
        cookie     : true,
        xfbml      : true,
        version    : 'v2.8'
      });
      FB.AppEvents.logPageView();
      FB.Event.subscribe('auth.statusChange', function(response) {
        if (response.authResponse) {
          this.checkLoginState();
        } else {
          console.log('---->User cancelled login or did not fully authorize.');
        }
      }.bind(this));
    }.bind(this);

    // Load the SDK asynchronously
    (function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = '//connect.facebook.net/en_US/sdk.js';
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
  }

  // Here we run a very simple test of the Graph API after login is
  // successful.  See statusChangeCallback() for when this call is made.
  testAPI() {
    console.log('Welcome! Fetching your information.... ');
    FB.api('/me', function(response) {
      console.log('Successful login for: ' + response.name);
      document.getElementById('status').innerHTML =
        'Thanks for logging in, ' + response.name + '!';
    });
  }

  // This is called with the results from from FB.getLoginStatus().
  statusChangeCallback(response) {
    if (response.status === 'connected') {
      // Logged into your app and Facebook.
      this.testAPI();
    } else if (response.status === 'not_authorized') {
      // The person is logged into Facebook, but not your app.
      document.getElementById('status').innerHTML = 'Please log ' +
        'into this app.';
    } else {
      // The person is not logged into Facebook, so we're not sure if
      // they are logged into this app or not.
      document.getElementById('status').innerHTML = 'Please log ' +
      'into Facebook.';
    }
  }

  checkLoginState() {
    FB.getLoginStatus(function(response) {
      this.statusChangeCallback(response);
    }.bind(this));
  }

  handleClick() {
    FB.login(this.checkLoginState());
  }

  render() {
    return (
      <main>
        <Grid fluid>
            <h1>
              Facebook Login
            </h1>
        </Grid>
        <Grid>
          <Row>
            <Col xs={12}>
              <a href="#" onClick={this.handleClick} onlogin={this.checkLoginState}>Login</a>
              <div id="status"></div>
            </Col>
          </Row>
        </Grid>
      </main>
    );
  }
}

Ответ 7

Попробуйте использовать эту библиотеку: https://github.com/keppelen/react-facebook-login

Работает довольно просто:

import React from 'react';
import ReactDOM from 'react-dom';
import FacebookLogin from 'react-facebook-login';

const responseFacebook = (response) => {
  console.log(response);
}

ReactDOM.render(
  <FacebookLogin
    appId="1088597931155576"
    autoLoad={true}
    callback={responseFacebook} />,
  document.getElementById('demo')
);

Ответ 8

Это, безусловно, самый чистый и простой способ, о котором я мог подумать, если вы хотите использовать кнопку из FB вместо своего.

Чтобы использовать кнопку, это так просто, как это.

<FbLoginBtn
  width="250"
  dataScope="public_profile,email"
  onSuccess={callback}
  onFailure={optionalCallback}
  afterLogin={optionalCallback}
/>

Этот компонент полностью автономный и сильно компостируемый, потому что он не полагается на какую-либо внешнюю зависимость и не имеет какого-либо предопределенного поведения, кроме того, что он делает кнопку входа в FB.

import React, { Component } from 'react';

class FbLoginBtn extends Component {
  constructor(props) {
    super(props);

    // post login behavior should be defined at a higher level
    this.onSuccess = this.props.onSuccess || (() => {});
    this.onFailure = this.props.onFailure || (() => {});
    this.onSuccess = this.onSuccess.bind(this);
    this.onFailure = this.onFailure.bind(this);
  }

  componentDidMount() {
    // This is the meat of the component
    // create a script tag, load FB SDK
    // then after script is loaded, set related behavior
    // If you have other components that rely on the FB SDK
    // I recommend extracting this into its own module
    let self = this;
    let scriptTag = document.createElement('script');
    scriptTag.type = 'text/javascript';
    scriptTag.src = "http://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.4&appId=xxxxx";
    scriptTag.addEventListener('load', function (e) {
      self.FB = window.FB;
      // I don't like exposing the SDK to global scope
      window.FB = null;

      // This subscribe the callback when login status change
      // Full list of events is here
      // https://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/v2.9
      self.FB.Event.subscribe('auth.statusChange', self.onStatusChange.bind(self));
    });
    document.body.appendChild(scriptTag);
  }

  onStatusChange(response) {
    if (response.status === 'connected') {
      const { accessToken } = response.authResponse;
      // I have a afterLogin optional callback
      // which takes care of ads landing, invitation or any other custom behavior
      this.onSuccess(accessToken, this.props.afterLogin);
    } else {
      this.onFailure();
    }
  }

  render() {
    return (
      <div 
        className="fb-login-button" 
        data-width={this.props.width}
        data-max-rows="1"
        data-size="large"
        data-button-type="login_with"
        data-show-faces="false"
        data-auto-logout-link="true"
        data-use-continue-as="false"
        data-scope={this.props.dataScope}
      >
      </div>
    );
  }
}

export default FbLoginBtn;