Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 390 Vote(s) - 3.45 Average
  • 1
  • 2
  • 3
  • 4
  • 5
pass state around between express middleware in an isomorphic react app

#1
I have an isomorphic react app and I would like to somehow pass state between express middleware.

I have the following express route that handles form submission:

export const createPaymentHandler = async (req: Request, res: Response, next: NextFunction) => {
const { field } = req.body;

if (!paymentType) {
res.locals.syncErrors = { field: 'some error.' };
next();
return;
}

try {
const { redirectUrl } = await makeRequest<CreatePaymentRequest, CreatePaymentResponse>({
body: { paymentType },
method: HttpMethod.POST
});

res.redirect(redirectUrl);
} catch (err) {
error(err);

res.locals.serverError = true;

next();
}
};

The next middleware is handling the rendering.

At the moment I am using `res.locals`, is there a better way or a recognised pattern?

Reply

#2
Because your handler is async, you need to pass the `err` into `next`, like so:

next(err);

In order for your middleware to process the error, instead of it being picked up by the default error handler, you need to have four parameters:

app.use((err, req, res, next) => {
// handle the error
})

It's also worth noting that error handlers need to be specified after other middleware. For your case, it might make sense to use a normal "success" middleware alongside an error handler, rather than combining the two into one middleware.

Finally, keep in mind that passing `err` as a parameter is specific to error handlers. If you just want to pass some data into your next middleware, you would do that by modifying the `req`:

req.x = 'some data'
next()

Then, the next middleware's `req` parameter will have the data you set.

---

Further reading:

[To see links please register here]

Reply

#3
IMO your question is more about passing some data to the next middleware. Since the rendering logic is handled by the next middleware, the express route shouldn't be concerned by how the data is being used. Your approach looks fine.

[`res.locals`](

[To see links please register here]

) is the recommended way of passing data to the next middleware. From the docs:

> This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on.

Also, since the variables added will be scoped to the current request, thus the data will only be available for the current request's lifecycle. Perhaps you can set a convention of adding a `state` key on the `res.locals` to store all your state variables, but the current approach would also work fine.
Reply

#4
If it's passing lightweight information to the next middleware for rendering purposes then applying `res.locals` is fine. However, you might want to look into custom `error-handling` for general errors, such as internal error.

Consider the following error handling

function notFoundHandler(req, res, next) {
res.status(404).render('notFoundPage', {
error: '404 - not found'
});
}

function badRequestHandler(err, req, res, next) {
res.status(400).render('badRequestPage', {
error: 'Bad request'
});
}

function errorHandler(err, req, res, next) {
res.status(err.status || 500).render('errorPage', {
error: 'Internal server error'
});
}

app.use(notFoundHandler);
app.use(badRequestHandler);
app.use(errorHandler);


Now instead of passing error details to the next middleware you would simple let it *flow* to the error handlers, e.g.

export const createPaymentHandler = async (req: Request, res: Response, next:

NextFunction) => {
const { field } = req.body;

if (!paymentType) {
res.status(400);
return next(); // This will hit the Bad Request handler
}

try {
const { redirectUrl } = await makeRequest < CreatePaymentRequest, CreatePaymentResponse > ({
body: { paymentType },
method: HttpMethod.POST
});

res.redirect(redirectUrl);
} catch (err) {
res.status(500);
return next(err); // This will hit the Error Handler
}
};
Reply

#5
`res.locals` is a standard way to pass data to the next middleware in the scope of the current request. Since your use case is around the current request, it makes sense to do so.

At the same time, the standard way to handle errors is to pass the error to the next middleware.

next(err);

Then you can handle the error scenario from the error handler. However, for an isomorphic react app, this would make things harder. So if you decide to go down that path, I would suggest you to use a custom error like `PaymentError` by extending `Error`. This would make even more sense since you are already using Typescript.

However, when you actually think about this scenario, when the error is not a request error, from the point of view of the react app, it is a special state/property of rendering. Thus I suggest the following hybrid approach.

1. If the error is of high priority, that is, if the error should stop rendering the expected content and fallback to a special page, use the `next(err)` approach.
2. If the error should just be part of the state report, then use the `res.locals` approach.
Reply

#6
The best way to pass a state between express middleware is to use the object `res.locals` what you already do.

**You are on the correct and best way!**

May be you have to look to **[the documentation from `res.locals`][1]** one time again:

<!-- language: lang-js -->

> **Citate from documentation of `res.locals`**
>
> `res.locals` – an object that contains response local variables scoped to the
> `request`, and therefore available only to the view(s) rendered during
> that `request` / `response` cycle (if any). Otherwise, this property is
> identical to `app.locals`.
>
> This property is useful for exposing `request-level` information such as
> the request path name, authenticated user, user settings, and so on.
>
> app.use(function(req, res, next)
> {
> res.locals.user = req.user;
> res.locals.authenticated = ! req.user.anonymous;
> next();
> });

And you can see – they recommend to use this object.

You are on the **right way!**


[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through