How to make initial authenticated request with token from local storage? - reactjs

I'm using vanilla flux with some utils for communicating with my APIs.
On initial page load I'd like to read some token from local storage and then make a request to my API to get my data.
I've got a LocalStorageUtils.js library for interacting with window.localStorage. My container component handles all login/logout actions and reads the current user on page load.
App.js
componentWillMount() {
LocalStorageUtils.get('user');
}
LocalStorageUtils reads the value and brings it into Flux via ServerAction similar to the flux chat example.
get(key) {
var value = window.localStorage.getItem(key);
if (value) {
ServerActionCreators.receiveFromLocalStorage(key, value);
}
}
That puts the user into my UserStore and into my views where I can show the username and some logout link, etc.
I also have ApiUtils.js for requesting data from the server. So the question is: Where do I tell my ApiUtils that I have a logged-in user at initial page load?
I could call some method inside ApiUtils from my LocalStorageUtils but that does not feel right.
Or do I have to make another round trip whenever I get a change event inside my container component?

You should pass the user as data to your ApiUtils class and removing the need from being concerned about how your ApiUtils is used.
var ApiUtils = function () {
this.get = function (endpoint, data) {
return theWayYouSendAjaxRequests.get(endpoint).setData(data);
};
};
// Wherever your ApiUtils is used.
var api = new ApiUtils();
api.get('/me', {user: userFromStore});

I found a solution that works and feels right.
As getting data from local storage is synchronous there is no need to pipe it through Flux via ServerActionCreators. Simply use LocalStorageUtils to get the current user and call the login method with that user. The login Action is the same you would use when a user initially logs in. login triggers getting new data from server. The new data is saved in my DataStore and the user is saved to my UserStore.
Thanks for all hints at Twitter and at https://reactiflux.slack.com/.

Related

Specifically, how does Reactjs retrieve data from firebase function triggers?

I am using express to create my firebase functions, and I understand how to create regular callable functions. I am lost however on the exact way to implement trigger functions for the background (i.e. onCreate, onDelete, onUpdate, onWrite), as well as how Reactjs in the frontend is supposed to receive the data.
The scenario I have is a generic chat system that uses react, firebase functions with express and realtime database. I am generally confused on the process of using triggers for when someone sends a message, to update another user's frontend data.
I have had a hard time finding a tutorial or documentation on the combination of these questions. Any links or a basic programmatic examples of the life cycle would be wonderful.
The parts I do understand is the way to write a trigger function:
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onWrite((change, context) => {
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
// Grab the current value of what was written to the Realtime Database.
const original = change.after.val();
console.log('Uppercasing', context.params.pushId, original);
const uppercase = original.toUpperCase();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
// Setting an "uppercase" sibling in the Realtime Database returns a Promise.
return change.after.ref.parent.child('uppercase').set(uppercase);
});
But I don't understand how this is being called or how the data from this reaches frontend code.
Background functions cannot return anything to client. They run after a certain event i.e. onWrite() in this case. If you want to update data at /messages/{pushId}/original to other users then you'll have to use Firebase Client SDK to listen to that path:
import { getDatabase, ref, onValue} from "firebase/database";
const db = getDatabase();
const msgRef = ref(db, `/messages/${pushId}/original`);
onValue(msgRef, (snapshot) => {
const data = snapshot.val();
console.log(data)
});
You can also listen to /messages/${pushId} with onChildAdded() to get notified about any new node under that path.

react manage query string called data

I don't know how to manage query string to react.
I made component class and it is composed of 3 other components.
It is not show data first time. Users have to select or click but
ton.
It is work well.
But I received a new feature. ;(
When users connect my site who copied url, the page has to show data immediately.
So I added query string. But I don't know when I call function.
I installed query-string.
I tried to use 'shouldComponentUpdate' function, but it was not work.
shouldComponentUpdate(nextProps, nextState) {
if (this.props.location.search.ids !== nextProps.location.search.ids) {
// call some function....
}
return true;
}
for example,
Users connect localhost:3000/my/home
It's ok.
But users connect localhost:3000/my/home?ids=1
It's not ok.
Summary.
I want to show data immediately when user connect to the site by query-string.
to fetch data, the most common way to call api is calling in componentDidMount.
https://reactjs.org/docs/faq-ajax.html
if you are using react-router for your app, you can easily get query string with following feature of react-router .
https://reacttraining.com/react-router/web/example/query-parameters
and then pass query string to your api.
I added componentDidMount and call myfunction.
componentDidMount(){
const query = queryString.parse(this.props.location.search);
if(query.ids !== 'undefined'){
let slice_ids = [];
slice_ids = query.ids.split(',');
if(slice_ids.length > 0){
this.myfunction(1);
}
}
}
Users can access the url.
Thanks #gnujoow

My flux store gets re-instantiated on reload

Okay. I'm kinda new to react and I'm having a #1 mayor issue. Can't really find any solution out there.
I've built an app that renders a list of objects. The list comes from my mock API for now. The list of objects is stored inside a store. The store action to fetch the objects is done by the components.
My issue is when showing these objects. When a user clicks show, it renders a page with details on the object. Store-wise this means firing a getSpecific function that retrieves the object, from the store, based on an ID.
This is all fine, the store still has the objects. Until I reload the page. That is when the store gets wiped, a new instance is created (this is my guess). The store is now empty, and getting that specific object is now impossible (in my current implementation).
So, I read somewhere that this is by design. Is the solutions to:
Save the store in local storage, to keep the data?
Make the API call again and get all the objects once again?
And in case 2, when/where is this supposed to happen?
How should a store make sure it always has the expected data?
Any hints?
Some if the implementation:
//List.js
componentDidMount() {
//The fetch offers function will trigger a change event
//which will trigger the listener in componentWillMount
OfferActions.fetchOffers();
}
componentWillMount() {
//Listen for changes in the store
offerStore.addChangeListener(this.retriveOffers);
}
retrieveOffers() {
this.setState({
offers: offerStore.getAll()
});
}
.
//OfferActions.js
fetchOffers(){
let url = 'http://localhost:3001/offers';
axios.get(url).then(function (data) {
dispatch({
actionType: OfferConstants.RECIVE_OFFERS,
payload: data.data
});
});
}
.
//OfferStore.js
var _offers = [];
receiveOffers(payload) {
_offers = payload || [];
this.emitChange();
}
handleActions(action) {
switch (action.actionType) {
case OfferConstants.RECIVE_OFFERS:
{
this.receiveOffers(action.payload);
}
}
}
getAll() {
return _offers;
}
getOffer(requested_id) {
var result = this.getAll().filter(function (offer) {
return offer.id == requested_id;
});
}
.
//Show.js
componentWillMount() {
this.state = {
offer: offerStore.getOffer(this.props.params.id)
};
}
That is correct, redux stores, like any other javascript objects, do not survive a refresh. During a refresh you are resetting the memory of the browser window.
Both of your approaches would work, however I would suggest the following:
Save to local storage only information that is semi persistent such as authentication token, user first name/last name, ui settings, etc.
During app start (or component load), load any auxiliary information such as sales figures, message feeds, and offers. This information generally changes quickly and it makes little sense to cache it in local storage.
For 1. you can utilize the redux-persist middleware. It let's you save to and retrieve from your browser's local storage during app start. (This is just one of many ways to accomplish this).
For 2. your approach makes sense. Load the required data on componentWillMount asynchronously.
Furthermore, regarding being "up-to-date" with data: this entirely depends on your application needs. A few ideas to help you get started exploring your problem domain:
With each request to get offers, also send or save a time stamp. Have the application decide when a time stamp is "too old" and request again.
Implement real time communication, for example socket.io which pushes the data to the client instead of the client requesting it.
Request the data at an interval suitable to your application. You could pass along the last time you requested the information and the server could decide if there is new data available or return an empty response in which case you display the existing data.

AngularJS: How to login once and do not need to login again

I have implemented the authentication/authorization using AngularJS, Jersey REST and Spring Security. After logged in, call the following "create" method to store the user information:
.factory('Session', function () {
this.create = function (user) {
this.id = user.sessionId;
this.username = user.username;
this.userRoles = user.roles;
};
... ...
return this;
})
But, the problem is, every time I do one of the following 2 things, the stored information is lost and I have to login again:
Reload the whole page by pressing F5 or reload icon of browser
OR
Access the same URL from browser address bar
Could you please help me on how to reserve this information to guarantee login only once?
Thanks,
Check out sessionStorage. Not sure what the rest of your code looks like, but presumably your controller could save the Session created by your factory into sessionStorage.

How to store user session in secha touch 2

Im using Sencha Touch 2 where i have a login form asking for username and password
now i want to store user details via Session/Cookie so the user can logout,
i browsed some links which i got
Sencha-touch : save login / password (save session, multi-tasks)
but im being an new to sench touch develpment
any help using code examples will be of very great input for me
Thanks in advance
You can use the HTML5 localStore object. For instance, when a user logs in and your server request is made, on the callback of a successful server request you can store any necessary data. Here is a snippet from one of my apps:
loginCallback: function(options, success, response) {
this.mainSplash.setMasked(false);
var responseOjbect = Ext.JSON.decode(response.responseText);
if (responseOjbect.success) {
this.clearLoginStorage(); //runs a function to clear some login storage values
if (rememberme) {
localStorage.setItem("rememberme", 1);
} else {
localStorage.setItem("rememberme", 0);
}
localStorage.setItem("userid", responseOjbect.userid);
localStorage.setItem("first_name", responseOjbect.first_name);
localStorage.setItem("last_name", responseOjbect.last_name);
localStorage.setItem("appsettingone", responseOjbect.appsettingone);
localStorage.setItem("appsettingtwo", responseOjbect.appsettingtwo);
localStorage.setItem("setdate", new Date());
if (!this.dashboard) {
Ext.create('myApp.view.Dashboard', {
//additional config
});
}
Ext.Viewport.setActiveItem(this.dashboard);
} else {
Ext.Msg.alert('Attention', responseOjbect.errorMessage, Ext.emptyFn);
}
}
Once you have set your localStorage items, they can be retrieved or removed like so:
localStorage.getItem("user_id"); //retrieve
localStorage.removeItem("userid"); //remove
So when you call your logout function, just don't remove any localStorage objects you want to keep. Then you can call localStorage.getItem("VALUE") to retrieve them upon next login
This is something which is managed by the server, not the client, so you want to look at , not at sencha itself.
On a guess that you are using php, for something really basic, take a look at:
http://www.html-form-guide.com/php-form/php-login-form.html

Resources