javascript - español - Implementar el inicio de sesión de la API de Facebook con reactjs
facebook sdk login button (9)
Estoy trabajando en el uso del Javascript SDK de Facebook para la autenticación. Pude importar el SDK correctamente y poner un botón Me gusta en mi página. Pero, el botón de inicio de sesión de Facebook debe estar envuelto en la etiqueta:
<fb:login-button/>
Actualmente tengo todo el código del tutorial de inicio de sesión de Facebook pegado en mi index.html, el único archivo html en mi proyecto, que alberga la aplicación React. Pero, necesito poner la última parte, que tiene el botón de inicio de sesión real, en mi componente Reaccionar. Cuando traté de hacer eso, recibí el siguiente error:
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''s settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App''s domains.
¿Cómo puedo hacer que el botón de inicio de sesión reaccione?
Escribí una clase mixin para abordar esto.
Esta es la solución que utilicé para obtener una devolución de llamada de inicio de sesión. Puede agregar este código para su botón de inicio de sesión de Facebook en su método de renderizado :
<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>
En tu código, agrega estas líneas:
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''));
}
}
Llamar a FB.Event.subscribe (''auth.statusChange'', callback_function) durante la inicialización del componente es importante porque esa es básicamente su devolución de llamada de inicio de sesión. FB.Event aquí la documentación de FB.Event .
Esta es, de lejos, la manera más simple y clara en la que podría pensar si desea usar el botón de FB en lugar del suyo.
Para usar el botón, es tan simple como esto.
<FbLoginBtn
width="250"
dataScope="public_profile,email"
onSuccess={callback}
onFailure={optionalCallback}
afterLogin={optionalCallback}
/>
Este componente es completamente autónomo y altamente compostable porque no depende de ninguna dependencia externa ni tiene un comportamiento predefinido que no sea la representación del botón de inicio de sesión del 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;
Hace poco estuve trabajando en el inicio de sesión de Facebook para uno de mis proyectos, así que después de recorrer muchas respuestas de y publicaciones en el blog. Escribí un código minimilastic usando ES6 FatArrow Function Expression (excluyendo .bind (this)) . Espero que este código te ayude.
https://gist.github.com/ronit-mukherjee/3e933509643a4ab4e80452bb05c1a073
/*global FB*/
import React, {
Component
} from ''react'';
class FacebookLoginButton extends Component {
componentDidMount() {
(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 = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, ''script'', ''facebook-jssdk''));
window.fbAsyncInit = () => {
FB.init({
appId: ''9999999999999999'', //Change with your Facebook app id
autoLogAppEvents: true,
xfbml: true,
version: ''v3.0''
});
FB.Event.subscribe(''auth.statusChange'', response => {
if (response.authResponse) {
this.checkLoginState();
} else {
console.log(''[FacebookLoginButton] User cancelled login or did not fully authorize.'');
}
});
};
}
checkLoginState() {
FB.getLoginStatus(function(response) {
this.statusChangeCallback(response);
}.bind(this));
}
login() {
FB.login(this.checkLoginState(), {
scope: ''email''
});
}
statusChangeCallback(response) {
if (response.status === ''connected'') {
this.testAPI();
} else if (response.status === ''not_authorized'') {
console.log("[FacebookLoginButton] Person is logged into Facebook but not your app");
} else {
console.log("[FacebookLoginButton] Person is not logged into Facebook");
}
}
testAPI() {
FB.api(''/me'', function(response) {
console.log(''[FacebookLoginButton] Successful login for: '', response);
});
}
render() {
return ( <
button className = "btn btn-block btn-fb"
onClick = {
() => this.login()
} >
<
i className = "fa fa-facebook" / > Connect with Facebook <
/button>
)
}
}
export default FacebookLoginButton;
He descubierto cómo modificar el tutorial de Facebook para la API de inicio de sesión con ReactJS. Espero que esto ayude a cualquier otra persona que esté luchando con esto.
En primer lugar, en el componente de reacción donde desea el enlace de inicio de sesión, incluya este código:
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());
},
Luego, en su método de renderizado, asegúrese de tener algún código HTML que llame a ese handleClick:
<a href="#" onClick={this.handleClick}>Login</a>
Tenga en cuenta que este es el mismo código del tutorial, pero colocado en un componente ReactJS. La única diferencia es que debe unir esto estratégicamente para hacer que las funciones de la API de Facebook sean parte de su componente de reacción. Este inicio de sesión finalizará con un mensaje de respuesta analizado a partir de la respuesta dada por FB.getLoginStatus (). También puede sacar el token de ese objeto de respuesta y enviarlo a su back-end para autenticación con algo como passport-facebook-token .
Intente utilizar esta biblioteca: https://github.com/keppelen/react-facebook-login
Funciona bastante sencillo:
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'')
);
Publiqué mi solución aquí, ya que las respuestas me ayudaron a implementarla, pero la respuesta aceptada de ritmatter no funcionó sin la
FB.Event.subscribe(''auth.statusChange'', function(response)
declaración de la respuesta de RubyFanatic. Además, el "onlogin" me confundió mucho. Simplemente no es requerido a mis ojos.
Quiero compartirlo, ya que esta es una solución de c & p, aquí mi código completo contra fb api v2.8 (reaccionar-bootstrap puede ser pateado por supuesto):
/* 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>
);
}
}
Usé Promises para el flujo de Auth de Facebook
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>
);
}
});
ritmatter dio una buena respuesta, pero le mostraré cómo lo hice de manera diferente. Quería usar el botón de inicio de sesión de Facebook en lugar del mío para activar la devolución de llamada para verificar el estado de inicio de sesión. El botón de inicio de sesión puede verse así:
<div class="fb-login-button" onlogin="checkLoginState" data-size="medium" data-show-faces="false" data-auto-logout-link="false"></div>
El botón tiene un atributo onlogin, que el analizador jsx no admite. Utilizar data-onlogin en reaccionar no funcionaba, así que acabo de agregar el botón en 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>
);
}
Todo lo que queda por hacer es activar el botón al montar el componente si desea llamar automáticamente a checkLoginState.