Devise - одно из самых популярных решений аутентификации для Rails из-за его высокой универсальности, ясной документации и большого сообщества. Однако мне не удалось найти никаких руководств или документации по его интеграции с React в гем Webpacker, поэтому я решил выложить свое собственное решение.

Я предполагаю, что вы можете настроить приложение Rails с React через гем Webpacker самостоятельно, и что у вас уже установлен Devise с созданной, перенесенной и готовой к работе пользовательской моделью. Я также предполагаю, что вы имеете базовое представление о React и жизненном цикле React.

Во-первых, вам понадобится компонент-контейнер. Скорее всего, это будет ваш файл App.jsx, потому что вы захотите передать информацию о текущем пользователе всем остальным вашим компонентам через свойства. Мы будем использовать Axios, поэтому убедитесь, что вы установили его на yarn, прежде чем мы начнем.

class App extends React.Component {
constructor(){
    super();
    this.state = {
      currentUser: null
    }
    this.updateCurrentUser = this.updateCurrentUser.bind(this);
  }
componentDidMount(){
    let that = this
    axios.get('/users/check_for_user',{
    })
    .then(function(response){
      if(response.data.email){
        that.setState({
          currentUser: response.data.email
        })
      } else {
        that.setState({
          currentUser: null
        })
      }
    })
    .catch(function(error){
      console.log(error);
    })
  }
updateCurrentUser(email) {
    this.setState({
      currentUser: email
    })
  }
render(){
    return (
      <div>
        <Header updateCurrentUser={this.updateCurrentUser}/>
      </div>
    )
  }
}

В этом компоненте мы установили состояние по умолчанию на null без пользователя.

Затем у нас есть функция, которая будет вызывать Axios к настраиваемому маршруту, который проверяет, вошел ли пользователь в систему или нет. В моем контроллере Rails я отправляю JSON-версию метода Devise current_user, если кто-то вошел в систему, и пустой пользовательский объект, если кто-то нет. Помещение этого в фазу DidMount жизненного цикла React позволяет пользователю оставаться в системе даже после обновления страницы. Этот вызов позволяет вам использовать Devise с React вместо передачи токенов.

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

Header.jsx

class Header extends React.Component {
constructor(props){
    super(props);
    if (this.props.currentUser == null){
      this.state = {
        page:"login"
      }
    } else{
      this.state = {
        page: "delete"
      }
    }
    this.changePage = this.changePage.bind(this);
  }
changePage(newPage) {
    this.setState({
      page: newPage
    })
  }
render() {
    switch(this.state.page) {
      case "signup":
        return <Signup changePage={this.changePage} updateCurrentUser={this.props.updateCurrentUser}/>
      case "login":
        return <Login changePage={this.changePage} updateCurrentUser={this.props.updateCurrentUser}/>
      case "delete":
        return <Logout changePage={this.changePage} updateCurrentUser={this.props.updateCurrentUser}/>
    }
  }
}

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

Регистрация.jsx

class Signup extends React.Component {
  constructor(props){
    super(props);
    this.handleSignup = this.handleSignup.bind(this);
  }
handleSignup(e) {
    e.preventDefault();
    let that = this
    axios.post('/users', {
      user: {
        email: document.getElementById("email").value,
        password: document.getElementById("password").value,
        password_confirmation: document.getElementById("password_confirmation").value
      }
    })
    .then(function(response){
      that.props.changePage("delete");
      that.props.updateCurrentUser(email);
    })
    .catch(function(error){
      console.log(error)
    })
}
render() {
  return (
      <div>
        <h2>Signup</h2>
        <form>
          <input id="email" placeholder="email"/>
          <input id="password" placeholder="password"/>
          <input id="password_confirmation" placeholder="retype password"/>
          <button onClick={this.handleSignup}>Submit</button>
        </form>
        <button onClick={() => this.props.changePage("login")}>Back to Login</button>
      </div>
    );
  };
};

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

Логин выглядит так же, как Регистрация, поэтому я закончу…

Logout.jsx

class Logout extends React.Component {
constructor(props){
    super(props);
    this.handleLogout = this.handleLogout.bind(this);
  }
handleLogout(e) {
    e.preventDefault();
    let that = this
    let email = this.props.currentUser
    axios.delete('/users/sign_out', {
    })
    .then(function(response){
      that.props.changePage("login")
    })
    .catch(function(error){
      console.log(error)
    })
  }
render() {
    return (
      <button onClick={this.handleLogout}>Sign Out</button>
    );
  };
}

Как видите, интегрировать Devise через Webpacker не так уж сложно для быстрой и простой системы аутентификации, когда вы не хотите связываться с передачей токенов в React.

📝 Прочтите этот рассказ позже в Журнале.

👩‍💻 Просыпайтесь каждое воскресное утро и слушайте самые интересные истории из области технологий, ожидающие вас в вашем почтовом ящике. Прочтите информационный бюллетень« Примечательно в технологиях .