connect-flash - Express

connect-flash とは

connect-flashを使うとフラッシュメッセージを表示することができます。

セッションとクッキーが使われるので、cookie-parserexpress-sessionが必要になります。

Express Generatorを使った場合は、cookie-parserは、自動的にインストールされます。

インストール

// connect-flash
npm install connect-flash

// express-session
npm install express-session

// まとめてインストール
npm install connect-flash express-session

2025/03/01 現在、利用はできますが 「 connect-flash 」を利用すると以下のエラーが表示されます。

(node:13532) [DEP0044] DeprecationWarning: The `util.isArray` API is deprecated. Please use `Array.isArray()` instead. (Use `node --trace-deprecation ...` to show where the warning was created)

インストールした connect-flash(node_modules/connect-flash/lib/flash.js)のファイルを編集して、util.isArray の使わないように書き換えると警告はでなくなります。

connect-flash@0.1.1

/**
 * Module dependencies.
 */
var format = require('util').format;
var isArray = require('util').isArray; // この行をコメントアウトもしくは、削除


/**
 * Expose `flash()` function on requests.
 *
 * @return {Function}
 * @api public
 */
module.exports = function flash(options) {
  options = options || {};
  var safe = (options.unsafe === undefined) ? true : !options.unsafe;
  
  return function(req, res, next) {
    if (req.flash && safe) { return next(); }
    req.flash = _flash;
    next();
  }
}

/**
 * Queue flash `msg` of the given `type`.
 *
 * Examples:
 *
 *      req.flash('info', 'email sent');
 *      req.flash('error', 'email delivery failed');
 *      req.flash('info', 'email re-sent');
 *      // => 2
 *
 *      req.flash('info');
 *      // => ['email sent', 'email re-sent']
 *
 *      req.flash('info');
 *      // => []
 *
 *      req.flash();
 *      // => { error: ['email delivery failed'], info: [] }
 *
 * Formatting:
 *
 * Flash notifications also support arbitrary formatting support.
 * For example you may pass variable arguments to `req.flash()`
 * and use the %s specifier to be replaced by the associated argument:
 *
 *     req.flash('info', 'email has been sent to %s.', userName);
 *
 * Formatting uses `util.format()`, which is available on Node 0.6+.
 *
 * @param {String} type
 * @param {String} msg
 * @return {Array|Object|Number}
 * @api public
 */
function _flash(type, msg) {
  if (this.session === undefined) throw Error('req.flash() requires sessions');
  var msgs = this.session.flash = this.session.flash || {};
  if (type && msg) {
    // util.format is available in Node.js 0.6+
    if (arguments.length > 2 && format) {
      var args = Array.prototype.slice.call(arguments, 1);
      msg = format.apply(undefined, args);
    // 以下の1行を「 } else if (Array.isArray(msg)){ 」に変更
    } else if (isArray(msg)) {
      msg.forEach(function(val){
        (msgs[type] = msgs[type] || []).push(val);
      });
      return msgs[type].length;
    }
    return (msgs[type] = msgs[type] || []).push(msg);
  } else if (type) {
    var arr = msgs[type];
    delete msgs[type];
    return arr || [];
  } else {
    this.session.flash = {};
    return msgs;
  }
}

Express フォルダ構成

routes/session.js

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.render('session/index');
});

router.post('/', function(req, res, next) {
  req.flash("text", req.body.message);
  res.redirect('/session/');
});

module.exports = router;

views/session/index.ejs

<!DOCTYPE html>
<html>
  <head>
    <title>connect-flash</title>
  </head>
  <body>
    <form action="/session" method="post">
      <input type="text" name="message">
      <input type="submit" value="送信">
    </form>
    <% if(messages.text){ %>
      <p><%= messages.text %></p>
    <% } %>
  </body>
</html>

app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const session = require("express-session"); // +
const flash = require('connect-flash'); // +

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var sessionRouter = require('./routes/session'); // +

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// + ルーターの設定の前に記述する必要があります
app.use(session({
  secret: "secret",
  resave: false,
  saveUninitialized: true,
}));
app.use(flash()); // + ルーターの設定の前に記述する必要があります

 // + ルーターの設定の前に記述する必要があります
app.use((req, res, next) => {
  res.locals.messages = req.flash(); // *1
  next(); 
});

// ルーターの設定
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/session', sessionRouter); // +

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

※1「 res.locals.messages = req.flash(); 」の messages の部分が、ビューで呼び出している <%= messages.text %> の messages の部分です。

messages の部分は、自由に変更できます。

「 res.locals.msg = req.flash(); 」とした場合、ビューでは <%= msg.text %> とすれば呼び出せます。