Anastasia – Page 2 – Visionmate – En fullservice digital partner

Förbättra React forms med Redux Form

Intro

Redux är ett utmärkt verktyg för att dramatiskt förbättra datahanteringen i din applikation. Då borde det vara ett naturligt steg att använda det också för dina application forms. Absolut, men varför återuppfinna hjulet igen?

Redux Form gör exakt det du kan förvänta dig – det använder application state för att hantera form data utan att du behöver skriva all kod själv.

I det här inlägget kommer jag gå igenom processen med att konfigurera Redux-form och ge några exempel på typiska fall.

Setup

Redux Form-inställningen innehåller följande steg:

Inkludera form reducer i combineReducers function (det måste göras en gång per form i din applikation)

import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
const rootReducer = combineReducers({  
/* Other reducers */  
    form: formReducer
});
export default rootReducer;

Link selected form to form reducer (låt oss säga att du har en komponent som heter LoginPage)

import {reduxForm} from "redux-form";

export default reduxForm({ 
  form: 'login' /* This must be unique */ 
})(LoginPage);

I själva komponenten måste du länka din form till en funktion som kommer att utföras när du submittar. Detta görs via “handleSubmit” som tillhandahålls av Redux Form.

const {handleSubmit} = props
return (
    <form onSubmit={handleSubmit(login)}>
      <Field
        name='username'
        placeholder = "Enter username"
        component="input"type='text'
      />
      <Field
        name='password'
        placeholder = "Enter password"
        component="input"
        type='password'
      />
      <button type="submit">Login</button>
    </form>
)

Out form innehåller två inmatningsfält (för användarnamn och lösenord) och en knapp.

Inloggningsfunktionen kan vara en komponentfunktion eller en redux-åtgärd – vi behöver bara lägga till den med hjälp av anslutningsfunktionen. Det kommer att användas för asynkron validering.

import {login} from "../actions/actions";

/* If you need to connect your component to redux,
it's best to do it before applying reduxForm HOC*/
LoginPage = connect (mapStateToProps, {login})(LoginPage);

export default reduxForm({
    form: 'login'    
})(LoginPage);

Synkron validering

För att minska belastningen på back-end och förbättra användarupplevelsen är det bäst att utföra synkron validering när det är möjligt – till exempel kan vi kontrollera om användarnamnet och/eller lösenordet innehåller ogiltiga tecken.

Det första steget är att lägga till valideringsfunktionen via reduxForm HOC (higher-order component):

export default reduxForm({
    form: 'login',
    validate
})(LoginPage);

Och lägg till själva valideringsfunktionen ovanför LoginPage container.

const validate = (values) => {
    const errors = {}
    if(!values.username) {
        errors.username = "Cannot be empty"
    }
    if(!values.password) {
        errors.password = "Cannot be empty"
    }
    return errors
}

När vi ändrar användarnamn eller lösenord, kommer den synkrona valideringen att köras och kontrollera om båda fälten är populated. Om en valideringsfunktion returnerar errors så kommer formuläret inte att skickas in.

Asynkron validering

Om form values framgångsrikt överför synkroniserad validering så skickas de vanligtvis till en server via ett asynkront anrop. Med hjälp av Redux-formuläret kan vi inaktivera formuläret tills vår begäran har behandlats och ett felmeddelande visas om det inte lyckades.

handleSubmit kommer utföra vår inloggningsåtgärd:

export function login(values) {    
    return (dispatch) => {        
        return ApiConnector.login(values.username, values.password)
            .then(response => {
                if(response.data.success === true){
                  dispatch({
                    type: LOGIN
                  })
                } else {
                  throw new SubmissionError({        
                    _error: "Login failed!"
                    })

                }
            }) 
            .catch((error) => {              
              throw new SubmissionError({        
                _error: "Login failed!"
              })
            })
    }
}

Eftersom denna åtgärd använder ett asynkront anrop, måste vi använda Redux Thunk middleware. Funktionen ApiConnector.login är en post request som skickas med hjälp av axios. För att asynkron validering ska fungera korrekt är det viktigt att returnera Promise-objektet.

Vi kan se att om förfrågan till servern misslyckas (till exempel om en server är nere) eller inloggningen misslyckas, då returneras ett felmeddelande tillbaka till vårt formulär.

Hur kan vi visa felmeddelandet? Vi ändrar vår form container för att extrahera felet från props och visa den ovanför knappen “Logga in”.

const {handleSubmit, error} = props
return (
  <form onSubmit={handleSubmit(login)}>
    <Field
      name='username'
      placeholder = "Enter username"
      component="input"
      type='text'
    />
    <Field
      name='password'
      placeholder = "Enter password"
      component="input"
      type='password'
    />
    {error && <strong>{error}</strong>}
    <button type="submit">Login</button>
  </form>
)

Initial values

Många gånger vill du att dina forms ska ha några initiala värden (möjligen baserat på tidigare användarval). Detta kan göras genom att lägga till initialValues-objektet till container props (till exempel genom mapStateToProps).

function mapStateToProps(state) {
  return {
    initialValues: {
      username: "admin"
    }
  }
}

Vanligtvis kommer initialvärden att fyllas på från application state.

Changing values programmatically

Det finns situationer, när ett värde ändras, eller du automatiskt vill ändra ett annat värde – till exempel om någon vill logga in med “gäst” användarnamn, så ändras lösenordet automatiskt till “gäst” också.

Först måste funktionen “ChangeChange” läggas till med reduxForm HOC.

export default reduxForm({
    form: 'login',
    validate,
    onChange
})(LoginPage);

onChange-funktionen kan läggas till ovanför Login Page komponenten.

import {reduxForm, change} from "redux-form";

const onChange = (values, dispatch, props, previousValues) => {
  if(values.username === "guest") {
    dispatch( change ('login', 'password', 'guest');
  }
}

Detta kan vara väl användbart om du har ett värde som är helt beroende av ett annat.

Sammanfattning

Genom att använda informationen i det här inlägget så bör du kunna implementera Redux Form i dina applikationer. Det är ett mycket kraftfullt verktyg, som i stort sett innehåller all den funktionalitet som behövs för hantering av application forms.

Om du behöver mer information så är det bästa stället att hitta det på här: www.redux-form.com

/ Radek

Origin: www.linkedin.com

Alla artiklar

Animation i React med React Transition Group

Häromdagen jobbade jag på ett nytt projekt utvecklat i React. En del av mitt jobb var att översätta statisk HTML till interaktiva React-components. Jag ville liva upp applikationen lite genom att använda animering.

Under lång tid sköttes det hela perfekt av jQuery. Men med uppkomsten av nya JavaScript-frames, som React och Angular, så försvann möjligheterna med jQuery. DOM-manipulation i React fungerar annorlunda. Komponenterna har livscykler som kan hoppa in och ut ur DOM.

Efter lite research kom jag över några animeringsbibliotek som exempelvis React Transition Group, React-spring, React-motion och andra. Vart och ett av dessa bibliotek har sina för- och nackdelar, några av dem var helt enkelt bara för krångliga att använda. Allt beror dock på projektets behov. Jag ville lägga till snygga bild- och övergångseffekter till vissa element. Det är egentligen en ganska enkel animering så jag bestämde mig för att välja React Transition Group  just på grund av dess enkelhet.

React Transition Group brukade vara en React add-on. Nu är det separerat och underhålls av communityn.

Jag vill nämna att React Transition Group-komponenterna inte ger oss själva animationen. I stället ger det oss en state för varje lifecycle så att vi kan tillämpa CSS-animering på komponenten när den ändrar state.

Låt oss ta en titt på hur det fungerar i praktiken. Jag har skapat en enkel sidebar. Den är gömd som standard och triggas av en knapp. När knappen klickas kommer komponenten att ändra state och producera en side bar.

import React, { Component } from "react";
import { render } from "react-dom";


class App extends Component {
//Initial state
 state = {
  show: false
 };

//Toggle show/hide sidebar
 toggleShow() {
  this.setState({
   show: !this.state.show
  });
 }

//Rendering sidebar
renderSidebar() {
 if(this.state.show) {
  return (
   <div
    style={{
     width: "50%",
      height: "100vh",
      paddingTop: '10px',
      background: "green",
      color: "white",
      textAlign: "center",
      transition: "all 1s ease",
      position: "absolute",
      top: 0,
      left: 0
     }}
    >
     Hi, there!
    </div>
   )
  } else {
    return null
   }
  }


 render() {
  return (
   <React.Fragment>
    {this.renderSidebar()}

    <button
     onClick={() => this.toggleShow()}
     style={{float: "right"}}>
      Button
    </button>

   </React.Fragment>
  );
 }
}


render(<App />, document.getElementById("root"));

Nu har vi fått igång det. Vi lägger till en fin slide effect när side bar dyker upp. Vi använder <Transition /> component. Låt oss först installera paketet och importera <Transition /> component till vår App.

npm install react-transition-group --save

import Transition from "react-transition-group/Transition";

Komponenten <Transition /> component kan finnas i fyra tillstånd: “Enter”, “entered”, “exiting” och “exited”. Det låter oss se dess beteende när det passerar från ett state till ett annat. Det tar också två huvudsakliga props: “timeout” och “in”.

I “timeout” -protokollet ställer vi in övergången i millisekunder. “In” -prop kommer att spåra staten. När “in” -värdet är lika med “true” flyttas en komponent till “in” -state och stannar där i 500ms innan man växlar till “inmatat” tillstånd. Samma process händer när “in” -värdet är lika med “false” – först flyttas en komponent till “exiting” och sedan till “exited” -state.

En annan viktig detalj jag vill nämna är att <Transition /> component returnerar en funktion med state som ett argument. Att placera children elements i det kommer inte att fungera.

Här är slutkoden.

import React, { Component } from "react";
import { render } from "react-dom";

//Import Transition component
import Transition from "react-transition-group/Transition";


class App extends Component {
//Initial state 
state = {
  show: false
 };

//Toggle show/hide sidebar
 toggleShow() {
  this.setState({
   show: !this.state.show
  });
 }


//Rendering sidebar
renderSidebar() {
 return (
  <Transition in={this.state.show} timeout={1000}>
   {state => (
    <div
     style={{
      width: "50%",
      height: "100vh",
      paddingTop: "10px",
      background: "green",
      color: "white",
      textAlign: "center",
      transition: "all 1s ease",
      position: "absolute",
      top: 0,
      //This is where all the magic happens :)
      left: state === "entering" || state === "entered" ? 0 : "-50%"
     }}
    >
     Hi, there!
    </div>
   )}
  </Transition>
 )
}


render() {
 return (
  <React.Fragment>
   {this.renderSidebar()}

   <button
    onClick={() => this.toggleShow()}
    style={{ float: "right" }} >
     Button
   </button>

  </React.Fragment>
  );
 }
}


render(<App />, document.getElementById("root"));

Som du kan se har jag justerat “renderSidebar ()” -funktionen. Jag har wrappat sidofältet med <Transition/> komponenten där “in” -prop lagrar staten och “timeout” är inställd på 1000ms. Allt det magiska sker på CSS ” “left” property. När state är lika med “inmatning” eller “inmatad” så tar den 0 och komponenten blir synlig. Annars flyttas den bort med -50 % (i förhållande till dess bredd) och blir osynlig.

Så här fungerar React Transition Group. Vi gör animationen med hjälp av CSS. Självfallet kan vi göra mycket mer med det. React Transition Group ger oss också andra komponenter så som <CSSTransition /> och <TransitionGroup /> där vi kan lägga till egna namn eller animera element i en lista.

Sammanfattningsvis vill jag säga att React Transition Group är ett utmärkt val för enkla animeringar.

/ Anastasia

Origin: www.linkedin.com

Alla artiklar

Kontinuerlig integration och Kontinuerlig Deployment med Jenkins Pipeline i Grails projects

Inledning

Programutveckling är spännande, men det är också ett yrke där du ständigt behöver utveckla och bredda din kompetens och ofta tänka utanför boxen. Förut hade mjukvaruföretagen bekymmer med att utveckla och leverera programvara snabbt och med bibehållen kvalitet. Det ledde så klart till att en stor andel projekt misslyckades. Sakta men säkert började man dock komma på metoder och processer för att upprätthålla flödet av s.k. hållbar utveckling.

För att vara konkurrenskraftig nu och/eller inom en snar framtid är det viktigt att möta efterfrågan på högkvalitativ mjukvara och implementera teknik som gör det möjligt för verksamheten att göra jobbet. Det finns många verktyg som kan hjälpa företaget att utveckla sina processer och hålla snabba kvalitativa lanseringar. Jag kommer i det här inlägget berätta om det kontinuerliga integrationsverktyget Jenkins, vilket är ett open source-verktyg som har många nyttiga och användbara tillägg. Jag kommer att visa hur man skapar en pipeline (Jenkins Declarative Pipeline) som ger en flexibel och kraftfull metod för att bygga, testa och deploya programvaror.

Mål

Skaffa allmän kunskap om kontinuerliga integrationsverktyg i mjukvaruprocessen, kunna automatisera integreringen och deployment av software pieces.

Systemkrav

Jenkins 2.73.3 (Om du använder Linux OS behöver du byta Batch skriptet mot Shell skriptet)

Grails 3. *

1.0. Kontinuerlig integration och Deployment strategi

Kontinuerlig integration är en mjukvaruutvecklingspraxis där medlemmar i ett team ofta samordnar sitt arbete. Vanligtvis integrerar varje person åtminstone på daglig basis, vilket leder till flera integreringar per dag. Varje integrering verifieras automatiskt (inklusive test) för att upptäcka eventuella integrationsfel så snabbt som möjligt (Martin Fowler, 2006).

Utvecklarna bör fokusera på utveckling och inte på implementeringsprocessen. Utvecklarens roll är att leverera kvalitetskod och programvara, när koden väl finns på plats så är utvecklaren inte ansvarig för den mer. Det låter ju bra tänker du, men hur löser man det? Det är inte en bra lösning att göra det manuellt, anledningen är att du då måste skapa en lokal miljö för att bygga och deploya mjukvaran. Om programvaran visar sig vara mer komplex så blir också byggnads- och installationsprocessen mer komplicerad. Det bästa sättet är därför att automatisera hela processen, i det här fallet kan en DevOps-ingenjör i ditt team med all säkerhet lösa processen. När koden väl finns på plats kommer den automatiskt att kompileras och deployas i alla olika miljöer med hjälp av varierande tekniker och verktyg. Utvecklarna kan då koncentrera sig på just utvecklingen.

2.0. Jenkins

Jenkins är ett välkänt verktyg för kontinuerlig integration. Verktyget har öppen källkod och gratis, det har även ett ganska stort utvecklar-Community. Med Jenkins kan du bygga ditt projekt, testa och deploya det i dina olika miljöer.

I verktyget är det möjligt att skapa olika typer av jobb eller objekt, bland dem kan du hitta “Freestyle-projektet” där du kan använda olika moduler för att bygga och deploya din programvara. “Jenkins pipeline” är ett mycket enkelt sätt att dra fördel av alla egenskaper hos Jenkins. Jenkins pipeline är dessutom mer flexibelt och anpassningsbart. I det här inlägget vill jag visa ett exempel på det.

2.1. Jenkins pipeline

Jenkins pipeline är ett Groovy-skript (Groovy är ett dynamiskt och modernt språk som översätts av Java Virtual Machine (JVM)). Pipen kan vara deklarativ eller scriptad, skillnaden är att deklarativ måste följa en viss syntax och den scriptade bör inte göra det. I det här fallet kommer vi att använda Declarative Pipeline. Declarative Pipeline har principiellt en enkel och användbar struktur där du kan dela upp ditt arbete steg för steg.

Nedan ser du en deklarativ Pipeline-struktur:

pipeline {
    agent any 
    stages {
        stage('Stage name') {
            steps{ 
            }
        } 
    }
}

Agent syntax specificerar var och hur pipen körs. Du kan lägga in många faser och var och en innehåller olika steg. I stegsyntaxen beskriver du den åtgärd du vill göra. Den deklarativa pipen är bred och innehåller många användbara syntaxer (se: https://jenkins.io/doc/book/pipeline).

Pipen kan implementeras i ett Jenkins-jobb eller som en Jenkinsfil i källan till ditt projekt, den senare är bara en fil som innehåller din deklarativa pipeline (se: https://jenkins.io/doc/book/pipeline/jenkinsfile/ ). Vidare kommer vi att använda Pipeline inom ett Jenkins-jobb.

2.1.1. Uppdatera från version control repository

I detta skede uppdaterar vi källkoden. Vi använder en Git-modul för att hantera den, den finns installerad som standard. Vi behöver bara ange vilken filial vi ska använda, webbadressen till repository och åtkomst-id. Vi kan konfigurera vår access-id i avsnittet “Credentials”.

stage(‘Pull’) {

    steps{
        git(branch: 'myBranch', 
            credentialsId: 'myId', url: 'https://github.com/myCompany/MyProject')
    }
}

2.1.2. Bygg ditt projekt

I det här skedet bygger vi projektet genom att köra ett Grails-kommando med batch modul. Genom att använd Grails i projektet så behöver vi bara köra ett kommando för att bygga det och ange var vi ska skapa vår .war-fil.

Senare måste vi arkivera vår artefakt för att få den tillgänglig för deployment eller något annat, vi använder wildcards för att ange sökvägen till artefakten.

stage('Build') {
    steps{
        bat(script: 'grails war', returnStatus: true)
        archiveArtifacts '**/build/libs/*.war'
    }
}

2.1.3. Testa ditt projekt

Grails 3. * använder Gradle som verktyg och med andra instrument, som exempelvis Ant och Maven, kan vi implementera tasks genom att anropa dem direkt eller i olika steg. När vår .war artefakt skapas kan vi testa vår mjukvara automatiskt. I det här fallet kan du köra ditt test i byggprocessen. I det här inlägget testar vi efter att ha byggt vårt projekt med en ny fas i Jenkins Pipeline.

stage('Test') { 
    when {
        expression { 
            def status = bat(returnStdout: true, script: 'grails test-app my.package.MyTestClass.myTestMethod | findstr BUILD')
            
            if(status.contains('BUILD') && status.contains('FAILED'))
                return true
               else 
                return false
        }
    }
    steps{
        error("TEST FAILED")
    }

}

I detta steg använde vi ett villkorat steg för att göra hela processen misslyckad om testet misslyckades.

2.1.4. Deploy

I det här fallet har vi Jenkins körande på samma server som vår applikationsserver och det är tillräckligt för att kopiera vår artefakt.

stage('Deploy') {
    steps {
        copyArtifacts(filter: '**/build/libs/*.war', flatten: true, projectName: 'MyProject', target: 'C:/www/MyProject', selector: specific('${BUILD_NUMBER}'))
    }
}

Med “selector: specific (‘$ {BUILD_NUMBER}’)” kommer vi att vara säkra på att kunna deploya vår artefakt (som genererats av det aktuella bygget).

2.2. Hook triggers

I avsnittet “Build Triggers” kan du se över “GitHub hook trigger för GITScm polling” options och i dina Github projektinställningar måste du lägga till en ny webhook med en hemlig nyckel som du behöver konfigurera även i Jenkins. Efter det, när Github upptäcker någon förändring i din filial, skickar den en notification till Jenkins som startar upp ditt jobb.

2.3. Ytterligare konfigurationer och tips

Om du använder Tomcat och får problem med att automatiskt deploya .war-filer så kan du lägga till nya steg i din pipeline:

stage('PreDeploy') {
    when {
        expression { 
            def status = bat(returnStdout: true, script: 'sc query Tomcat8 | findstr RUNNING || echo STOPPED')
           
            if(status.contains('STATE') && status.contains('RUNNING'))
                return true
               else 
                return false
        }
    }
    steps {
        bat(script:'net stop Tomcat8')
    } 
}

stage('Deploy') {
    steps {
        copyArtifacts(filter: '**/build/libs/*.war', flatten: true, projectName: 'MyProject', target: 'C:/www/MyProject', selector: specific('${BUILD_NUMBER}'))
    }
}

stage('PostDeploy') {
    steps {
        bat(script:'net start Tomcat8')
    }
}

Sammanfattning

Den tid du lägger på att förbättra utvecklingsprocessen, till exempel för att genomföra kontinuerlig integration och kontinuerlig deployment, är aldrig bortkastad och det kommer att säkerställa snabbare utgåvor, också ett fokus på utvecklingsprocesser och naturligtvis en nöjd kund. Jenkins pipeline erbjuder oss ett kraftfullt och enkelt sätt att göra det.

 / Carlos

 

Kommentera eller fråga gärna på mail:

info(@)visionmate.se

 

Referenser

Martin Fowler, 2006: Continuous Integration, https://www.martinfowler.com/articles/continuousIntegration.html

Alla artiklar

Hantera säkerhet i React med JWT

Under de senaste åren har det skett en stor förändring kring sättet vi använder programvara. Fokus har skiftats från stationära applikationer till lättdrivna applikationer i molnet (SaaS). Välkända företag som Facebook och Google har varit ledande i utvecklingen kring denna teknik.

Google har som exempel introducerat Angular, medan Facebook ligger bakom React, båda JavaScript bibliotek som används för att bygga webbgränssnitt.

På Visionmate har vi valt den senare alltså React för att bygga våra applikationer. I det här inlägget tänkte jag prata mer om hur vi hanterar själva säkerheten i applikationsutvecklingen.

JSON Web Token (JWT) är ett populärt sätt för att säkra upp och skydda dina processer (finns detaljerat i RFC 7519-standard).

Den stora fördelen med att använda en JWT-token (säkerhetsnyckel) är att du kan skjuta in extra information som bara kan avkodas av din back-end-kod.

Vi använder vi Grails för back-end och använder Spring Security REST-plugin för att generera och hantera JWT-tokens. Jag kommer inte gå in så mycket på just det idag, men jag eller någon annan i teamet planerar att skriva mer om ämnet framöver.

I det här exemplet använder jag Redux som state container inkluderat autentiseringsdata och nyckelinformation.

Inloggningsfunktionen skickar inte bara uppgifter om själva säkerhetsnyckeln utan även tilldelade användarroller. Anropet talar om alltså vilken typ av rättigheter användaren har – till exempel om de kan redigera vissa dokument eller få tillgång till adminpanelen.

API-inloggningsfunktionen (alla anrop görs med axios):

function login(user) {
        const config = {
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            }
        };
        return axios.post(`${SERVER_URL}/api/login`, user, config)       
    }

Login action:

export function login(username, password) {
    const user = {
        username,
        password
    };
    return (dispatch) => {
        ApiConnector.login(user)
            .then(response => {
                const data = response.data
                const user = {
                    access_token: data.access_token,
                    refresh_token: data.refresh_token,
                    roles: data.roles,
                    username: data.username,
                };
                sessionStorage.setItem('user', JSON.stringify(user));
                dispatch({
                    type: LOGIN,
                    user
                });
            })
            .catch((error) => {
                console.log(error)
            })
    }
}

Eftersom vi har en asynkron kommunikation så används redux-thunk middleware för att hantera den. Som du kan se innehåller svaret inte bara åtkomst- och uppdateringstoken, men även användarroller som senare kan användas för att till exempel göra ytterligare paneler på ett dashboard.

Nyckeln lagras sedan i antingen en session- eller lokal lagring beroende på applikationskraven, det här gör att användaren inte behöver logga in varje gång en webbläsare uppdateras.

Autentiseringsdatan lagras i en reducer:

export default function (state = {loggedIn: false}, action) {
    switch(action.type) {        
        case LOGIN:
            return {...state,
                user: action.user,                 
                loggedIn: true                
            };
        case LOGOUT:
            return {...state,
                user: {},
                loggedIn: false
            };
        default:
            return state
    }
}

En JWT-nyckel inkluderas i varje anrop. Därför kan den lagras i en separat JavaScript-fil som enkelt hämtas senare.

I det här fallet lagras den i headers.js:

export default () => {
    return {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${sessionStorage.getItem('user') ? JSON.parse(sessionStorage.getItem('user')).access_token : null}`
    }
}

Funktionen adderas sedan till varje API-anrop:

import headers from "../security/headers";

 function get(target, params) {
        const config = {
            headers: headers(),
            params
        }
        return axios.get(`${SERVER_URL}/api/${target}`, config)
    }

När säkerhetsnyckeln löper ut och blir ogiltigt så behöver användaren inte logga in igen – det är tillräckligt att använda uppdateringen för att få en ny giltig access.

Uppdatera token function:

function refreshToken() {
        const config = {
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        };
        const body = {
            grant_type: "refresh_token",
            refresh_token: JSON.parse(sessionStorage.user).refresh_token
        };
        axios.post(`${SERVER_URL}/oauth/access_token`, qs.stringify(body), config)
            .then(response => {
                const data = response.data
                const user = {
                    access_token: data.access_token,
                    refresh_token: data.refresh_token,
                    roles: data.roles,
                    username: data.username                    
                };
                sessionStorage.setItem('user', JSON.stringify(user));
                store.dispatch({
                    type: REFRESH_TOKEN,
                    user
                })
            })
    }

För att logga ut användaren, radera helt enkelt nyckeln från session/lokal lagring som visas i åtgärden nedan.

Logout action:

export function logout() {
    sessionStorage.removeItem('user');
    return {
        type: LOGOUT
    }
}

Summering

Som jag försökt visa i det här inlägget så måste vissa steg följas för att kunna använda JWT med din applikation. Du kan också använda exemplet som en mall för att lägga till mer funktionalitet och på så sätt utveckla din applikation.

/Radek

 

Bibliotek som används: redux, redux-thunk och axios.

Skicka gärna frågor och kommentarer till vår mail:

info(@)visionmate.se

 

Alla artiklar