【问题标题】:ReactJS + React Router: How to reference a specific object to pass down as properties?ReactJS + React Router:如何引用特定对象作为属性传递?
【发布时间】:2016-12-20 23:56:24
【问题描述】:

我目前有一个表格,每个单元格都有一个按钮。单击按钮后,根据特定日期(星期一或星期二)、班级(班级 1 或班级 2)和姓名(Kev 或 Josh),我如何将与表格中的特定按钮相关的对象推送到新的页?使用 ReactJS + React Router,正确的方法是什么?

一旦导航到新页面,新页面将使用传入对象的类信息填充一个表格,这些信息与单击的按钮单元格相关。

代码:

http://jsfiddle.net/k7wbzc4j/16/

表行数据是否应该像这样构造并基于 ID 引用对象,如下所示,或者什么是更好的结构 - 希望根据单元格位置定位特定的 id 对象(带有日期、名称,并考虑到班级编号)?

list: [
  {
    name: Kev
      monday: {
        class1: {
          id: 0,
          classTitle: abc,
          number: class1,
          info: {
            time: 1,
            classSize: 2,
          }
        },
        class 2: {
          id: 1,
          classTitle: def,
          number: class2,
          info: {
            time: 1,
            classSize: 2,
          }
        }
      },
      tuesday: {
        class1: {
          id: 2,
          classTitle: ghi,
          number: class1,
          info: {
            time: 1,
            classSize: 2,
          }
        },
        class 2: {
          id: 3,
          classTitle: jkl,
          number: class2,
          info: {
            time: 1,
            classSize: 2,
          }
        }
      },
  },

  {
    name: Josh, 
      monday: {
        class1: {
          id: 4,
          classTitle: mno,
          number: class1,
          info: {
            time: 1,
            classSize: 2,
          }
        },
        class2: {
          id: 5,
          classTitle: pqr,
          number: class2,
          info: {
            time: 1,
            classSize: 2,
          }
        }
      },
      tuesday: {
        class1: {
          id: 6,
          classTitle: stu,
          number: class1,
          info: {
            time: 1,
            classSize: 2,
          }
        },
        class2: {
          id: 7,
          classTitle: vwx,
          number: class2,
          info: {
            time: 1,
            classSize: 2,
          }
        }
      },
    }
  }
]

例如,如果 Kev 在 Monday 列中的行 class1 想将以下的 props 传递到下一页:

class1: {
  id: 0,
  classTitle: abc,
  number: class1,
  info: {
    time: 1,
    classSize: 2,
  }
}

将接受并投票赞成答案。提前谢谢你

【问题讨论】:

    标签: javascript reactjs react-router react-jsx


    【解决方案1】:

    这就是像redux 这样的集中式状态管理工具派上用场的地方。您可以调度一个操作(类似于SELECT_CLASS)在商店中设置选定的类,然后从您的新组件中读取该值。我会推荐这种方法。

    但是,还有另一种方法。每个浏览器历史记录条目都有一个state 的概念。因此,当您导航到新路由时,您可以将所选数据保存在该历史条目的状态中,然后在组件呈现时读取它。它看起来像这样:

    保存状态:

    router.push({
      to: '/path',
      state: class1
    });
    

    阅读:

    router.location.state
    

    React 路由器文档:https://github.com/ReactTraining/react-router/blob/master/docs/API.md#pushpathorloc

    更新:欢迎 redux!所以首先,让我们为此定义动作 + 动作创建者:

    export const SELECT_CLASS = 'SELECT_CLASS';
    export const selectClass = (class) => {
      return {
        type: SELECT_CLASS,
        class,
      }
    };
    

    现在,让我们看看处理这个问题的 reducer 是什么样子的:

    import { SELECT_CLASS } from '/path/to/action'
    
    const selectedClass = (
      state={},
      action
    ) => {
      switch (action.type) {
        case SELECT_CLASS:
          return action.class;
        default:
          returns state;
      }
    };
    

    现在,假设您已经像这样通过 react-redux 连接了组件:

    // First argument is mapStateToProps, the second is mapDispatchToProps
    // https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
    export default connect((state) => state, { selectClass } )(YourComponent);
    

    这是设置所选类的方式:

      // Wherever you need to navigate
      function eventHandler(e) {
        const { selectClass } = this.props;
        selectClass(class1);
        router.push('/next/location');
      }
    

    在你的下一个组件中(也应该连接,但不需要mapDispatchToProps

    render() {
      const { selectedClass } = this.props;
      // do what you need with the class.
    }
    

    如果您在设置 react + redux 时需要任何帮助,文档 here 非常棒。如果我使用的 ES6 语法看起来不熟悉,一个很好的参考是 babel docs here

    更新 2:我拿着你的小提琴跑了:http://jsfiddle.net/k7wbzc4j/17/。每个按钮都有一个点击事件,可以获取正确的对象。

    最终更新:这里是handleClick 的概要

    handleClick(e) {
        const classTitle = e.target.innerHTML;
        let obj = undefined;
        data.forEach((schedule) => {
          ['monday', 'tuesday'].forEach((day) => {
            const classes = schedule[day];
            return Object.keys(classes).forEach((c) => {
                const cls = classes[c];
                if (cls.classTitle === classTitle) {
                obj = cls;
              }
            });
          })
        });
    
        if (obj) {
          // do your navigation here
        }
      }
    

    首先,我们使用forEach 来遍历数组data,其中包含所有计划。然后,我们每天迭代(目前只有mondaytuesday)以获取当天所有课程的当前时间表。然后,由于我们不知道所有类的名称,我们只需获取所有键(即类名)并遍历它们。最后,我们可以获取实际的类对象并检查classTitle 是否与被单击的对象匹配。如果是这样,我们将该对象保存到obj。最后,我们确保我们找到了匹配的对象,然后做任何必要的事情来正确处理该点击。这很混乱,但考虑到您的数据结构,这是必要的。我建议尝试更相关地存储这些数据并分别存储每种类型的项目(例如UsersClassesDaysSchedules 对象都在单独的数组中,id 将它们链接在一起)

    为了解决您对某些classTitles 会相同的担忧,您还必须弄清楚谁的日程安排被点击了(可能还有被点击的那一天)。您可以通过多种方式做到这一点:为每个按钮添加data-user 属性并在单击时获取该属性,实现“选定用户”的概念,创建一个新组件(可能称为UserSchedule),在该表并将该用户的课程作为道具。这样,您将知道任何匹配的类都属于该用户。就像我说的:多种方式。

    至于向您展示如何将其传递给新组件,我在上面演示了如何做到这一点的两种方法:通过历史状态或将值存储在 redux reducer 中并将其作为 props 接收。再做就等于我为你解决了整个问题,我不会这样做,因为这些东西坚持下去的唯一方法就是让你自己做。相信自己,听从我给出的建议,并使用互联网解决您遇到的任何特定错误,然后您就会脱颖而出!

    【讨论】:

    • 我实际上正在使用 redux。在我接受答案并投票之前,您介意展示一个完整的周期吗,因为我一直坚持这个问题的时间最长。首先,您如何找到要传递给道具的确切道具?如果你能参考我的实际代码会更清楚。
    • 我理解循环,但我只是不明白我应该如何定位道具中的特定对象以通过。如果您可以在您的示例中使用我的实际道具和提供的代码,那真的很有帮助。例如,如果单击按钮abc,想传递对象:class1: { id: 0, classTitle: abc, number: class1, info: { time: 1, classSize: 2, } }。那么如何找到这个特定的对象呢?
    • 您介意简要介绍一下handleClick 中发生的事情吗?以及如何将找到的特定obj 推送到新页面的示例?
    • @taylorc93 想想const classTitle = e.target.innerHTML 会出问题,因为另一个classTitle 有同样的问题。
    • @taylorc93 是的,会有classTitle's 相同的案例
    猜你喜欢
    • 2021-04-18
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 2012-11-25
    • 2017-12-17
    • 1970-01-01
    相关资源
    最近更新 更多