【问题标题】:Fetching param.id data from front to backend - React / Node / Express从前端到后端获取 param.id 数据 - React / Node / Express
【发布时间】:2021-07-01 00:18:28
【问题描述】:

我正在尝试从我的后端返回一个组件上的用户列表,但我无法将我的用户 ID 参数传回。我正在使用 useEffect 从 Redux 中提取数据,然后使用我认为声明的参数调用组件上的操作。据我所见,正确的用户 ID 被正确传递,但是我认为当路由传递参数时会发生错误。

在我的操作中,我应该如何传递我想要获取数据的用户 ID 的参数?我有 console.log param.id/param.userID/userID 等。在组件中我有 user.userID(来自 useSelector)但是在操作文件夹中我不知道如何将它传递给后端。

另外在后端我是否总是必须将我的参数设置为 id?这些可以与前端的值具有相同的名称,例如“userID”吗?我似乎只能让后端 Postman 调用使用 :id。

组件

const user = useSelector(state => state.auth.user);

    const [userDiveLog, setUserDiveLog] = useState({
        user: [],
        userDiveLogList: [],

        expanded: false
    })

    // get access to dispatch
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(fetchUserDiveLog(user.userID));
    }, []);

动作

// pulls the user dive log
export function fetchUserDiveLog(params, credentials, diveLogUserList){
    return function(dispatch){
        return axios.get("http://localhost:5002/api/divelog/userdiveloglist/" + params.userID)
            .then(({data}) => {
                dispatch(userDiveLogList(data));
            });
    };
}

后端

路线

//  return an individual dive log
    app.get('/api/divelog/userdiveloglist/:userID', controller.userDiveLog);

控制器

exports.userDiveLog = (req, res, params, userID) => {

    try {
        const userID = req.params.userID

        diveLog.findAll({
            include: {all: true},
            where: {diverUserNumber: userID}
        })
            .then(diveLog => {
                const userDiveLogList = [];
                for (i = 0; i < diveLog.length; i++) {
                    userDiveLogList.push(diveLog[i].dataValues);
                }
                if (!userDiveLogList) {
                    return res.status(404).send({message: "No dive logs belonging to this user"});
                }
                res.status(200).send({
                    data: userDiveLogList
                })
            })
    } catch(err) {
            res.status(500).send({
                message: "Error retrieving dive log belonging to user id= " + id
            });
        }
};

【问题讨论】:

    标签: node.js reactjs ajax express parameters


    【解决方案1】:

    前端

    您将用户 ID(user.userID - 一个字符串)传递给 fetchUserDiveLog 函数,但您将其视为带有 userID 属性的 params 对象。 params.userID 返回 undefined,因为 params 是一个字符串(它包含用户 ID)。将 params 重命名为 userId 并将其添加到 URL。

    您还可以从 fetchUserDiveLog 函数中删除 credentialsdiveLogUserList 参数,因为它们没有被使用。

    export function fetchUserDiveLog(userId) {
      return (dispatch) => {
        return axios
          .get(`http://localhost:5002/api/divelog/userdiveloglist/${userId}`)
          .then(({ data }) => {
            dispatch(userDiveLogList(data))
          })
      }
    }
    

    顺便说一句,您不应该对 API URL 进行硬编码。使用环境变量。如果你使用Create React App,你可以使用add environment variables prefixed with REACT_APP_ to .env,或者如果你有自定义的Webpack设置,你可以使用dotenv-webpack

    后端

    后端代码存在一些问题。

    1. userDiveLog 函数接收next 函数作为第三个参数,但它被命名为params,这令人困惑。由于您不需要请求处理程序中的 next 函数,您应该从函数中删除 paramsuserID 参数。您可以从您正确执行的req.params 对象访问userID
    exports.userDiveLog = (req, res) => {
      // ...
    }
    
    1. if (!userDiveLogList) 条件永远不会为真,因为userDiveLogList 是一个在 JavaScript 中为真的数组。您实际上可以删除 if 块。如果用户没有任何Divelogs,则将发送{ data: [] } 的响应,这是完全可以的。您也可以省略status(200) 调用,因为状态会自动设置为200。并且您可以通过使用对象解构和Array.prototype.map 来重构代码来转换潜水日志。
    const { userID } = req.params
    
    const diveLogs = await diveLog.findAll({
      include: { all: true },
      where: { diverUserNumber: userID },
    })
    
    const data = diveLogs.map((log) => log.dataValues)
    res.send({ data })
    
    1. catch 块引用变量id,它没有在任何地方定义。应该改为userID

    整个代码使用async/await

    exports.userDiveLog = async (req, res) => {
      const { userID } = req.params
      try {
        const diveLogs = await diveLog.findAll({
          include: { all: true },
          where: { diverUserNumber: userID },
        })
        const data = diveLogs.map((log) => log.dataValues)
        res.send({ data })
      } catch () {
        res.status(500).send({
          message: `Error retrieving dive log belonging to user id= ${userID}`,
        })
      }
    }
    

    【讨论】:

      【解决方案2】:

      阅读说明后,我确定了两个问题,我将一次回答每个问题。

      是否必须将查询参数设置为Id?

      不,对查询参数的名称没有限制。您可以从字面上将其命名为“某物”。 也就是说,有一些约定规定您需要将参数命名为适当的名称。

      如何将userId 传递给我的 Action Creator?

      首先检查包装你的 Thunk 的函数。它需要 3 个参数:params(名称不好)、credentialsdiveLogUserList。 其中,它仅使用 1 个参数发送:userID

      重新配置此包装器函数以仅接收用户 ID 作为参数(并将凭据、diveUserList 作为额外参数发送到 Thunk 而不是包装器函数;这取决于您想要的功能,使用说明无法正确理解您提供的)。

      重新配置包装函数后,您将像这样调度相同的内容: fetchUserDiveLog(userID).

      处理你的路由的函数不正确

      如果我没记错的话,controller.userDiveLog 应该只接收 3 个参数,你已经用 4 个参数定义了你的处理程序。

      您的处理程序应该期待的参数是:requestresponsenext

      您的处理程序期望的用户 ID 将是一个查询参数,可以使用:request.params.userID 访问。

      不需要将 userID 作为处理程序的参数。

      其他信息

      我建议仔细阅读这些以获得更好的解释,此外,我建议使用console.log 作为调试代码的方法。它将帮助您识别以下问题:

      • 此函数接收多少个参数?
      • 收到的参数类型是什么?
      • 还有更多

      参考文献

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-28
        • 2022-01-21
        • 2022-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多