react & redux with hooks:动作必须是普通对象。使用自定义中间件进行异步操作

react & redux with hooks: Actions must be plain objects. Use custom middleware for async actions

我试图寻找类似的答案来帮助解决我的问题,但我找不到任何使用 react redux hooks 的东西。此代码来自教程,最初是使用上下文 api 编写的。我想尝试将它与 react-redux-hooks 一起使用,但我被卡住了。基本上我正在尝试使用名称、电子邮件和密码注册用户,然后将这三个作为对象传递给 express 服务器,该服务器将对其进行验证并返回给我一个 jwt 令牌。然后返回客户端并将令牌发送到 reducer,reducer 将令牌添加到 localstorage 并将状态设置为 isAuthenticated。我收到的错误是在发货时。

调度

const onSubmit = e => {
 e.preventDefault();

 if (name === "" || email === "" || password === "") {
  dispatch(setAlert("Please enter all fields", "danger"));
 } else if (password !== password2) {
  dispatch(setAlert("Passwords do not match", "danger"));
 } else {
  dispatch(register({ name, email, password })); // Error is here
 }

 setTimeout(() => {
  dispatch(removeAlert());
 }, 5000);
};

动作

 export const register = async formData => {
  const config = {
  headers: {
  "Content-Type": "application/json"
  }
 };

try {
const res = await axios.post("/api/users", formData, config);

return {
  type: "REGISTER_SUCCESS",
  payload: res.data
  };
} catch (err) {
return {
  type: "REGISTER_FAIL",
  payload: err.response.data.msg
  };
 }
};

减速器

const authReducer = (
 state = {
 token: localStorage.getItem("token"),
 isAuthenticated: null,
 loading: true,
 user: null,
 error: null
},
action
) => {
 switch (action.type) {
  case "REGISTER_SUCCESS":
   console.log("register success");
   localStorage.setItem("token", action.payload.token);
   return {
    ...state,
    ...action.payload,
    isAuthenticated: true,
    loading: false
   };

 case "REGISTER_FAIL":
   console.log("register failed");
   localStorage.removeItem("token");
   return {
    ...state,
    token: null,
    isAuthenticated: false,
    loading: false,
    user: null,
    error: action.payload
   };

 default:
   return state;
 }
};

商店

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ 
|| compose;

 const store = createStore(
 allReducers,
 composeEnhancers(applyMiddleware(thunk))
);

ReactDOM.render(
  <Provider store={store}>
   <App />
  </Provider>,
 document.getElementById("root")
);

快递服务器

router.post(
 "/",
  [
  check("name", "Please a name")
    .not()
    .isEmpty(),
  check("email", "Please include a valid email").isEmail(),
  check(
    "password",
    "Please enter a password with 6 or more characters"
   ).isLength({
     min: 6
   })
 ],
async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({
      errors: errors.array()
    });
  }

  const { name, email, password } = req.body;

  try {
   let user = await User.findOne({ email });

  if (user) {
    return res.status(400).json({
      msg: "User already exists"
    });
  }

  user = new User({
    name,
    email,
    password
  });

  // hash passsword
  const salt = await bcrypt.genSalt(10);

  user.password = await bcrypt.hash(password, salt);

  await user.save();

  const payload = {
    user: {
      id: user.id
    }
  };

  jwt.sign(
    payload,
    config.get("jwtSecret"),
    {
      expiresIn: 360000
    },
    (err, token) => {
      if (err) throw err;
      res.json({
        token
      });
    }
  );
} catch (err) {
  console.error(err.message);
  res.status(500).send("Server Error");
 }
}
);

我相信这个问题可以解答您在这里遇到的问题:how to async/await redux-thunk actions?

使用这个例子,它可能看起来像这样(无法测试):

export const register = formData => {
  const config = {
    headers: {
      "Content-Type": "application/json"
    }
  };

  const request = axios.post("/api/users", formData, config);

  return dispatch => {
    const onSuccess = success => {
      dispatch({
        type: "REGISTER_SUCCESS",
        payload: success.data
      });
      return success;
    };
    const onError = error => {
      dispatch({
        type: "REGISTER_FAIL",
        payload: error.response.data.msg
      });
      return error;
    };
    request.then(onSuccess, onError);
  };
};
export const register = formData => {
  const config = {
    headers: {
      "Content-Type": "application/json"
    }
  };

  return async dispatch => {
    const onSuccess = success => {
      dispatch({
        type: "REGISTER_SUCCESS",
        payload: success.data
      });
      return success;
    };
    const onError = error => {
      dispatch({
        type: "REGISTER_FAIL",
        payload: error.response.data.msg
      });
      return error;
    };

    try {
      const success = await axios.post("/api/users", formData, config);
      return onSuccess(success);
    } catch (error) {
      return onError(error);
    }
  }
};