ReactJS + React Router:如何引用特定对象作为属性传递? [英] ReactJS + React Router: How to reference a specific object to pass down as properties?

查看:60
本文介绍了ReactJS + React Router:如何引用特定对象作为属性传递?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I currently have a table and each cell has a button. Upon clicking the button, based on that particular day (Monday or Tuesday), class (class 1 or class 2), and name (Kev or Josh), how can I push an object related to that particular button in the table to a new page? Using, ReactJS + React Router, what would be the correct approach to this?

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

And when once navigated to the new page, the new page would then populate a table with the class information from the object passed in, related to button cell clicked.

代码:

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

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

Should the table rows data be structured like so and reference the object based on ID like the following, or what would be a better structure -- would like to locate that particular id object based on the cell location (with day, name, and class number taken into account)?

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 行,class1,想将以下道具传递到下一页:

For example, if the Kev's row in Monday column, class1, would like to pass the props of the following to the next page:

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

将接受并赞成答案.提前致谢

Will accept and upvote answer. Thank you in advance

推荐答案

这是集中状态管理工具的地方,例如 redux 就派上用场了.您可以分派一个操作(类似于 SELECT_CLASS)来设置存储中的选定类,然后从新组件中读取该值.我推荐这种方法.

This is where a centralized state management tool like redux comes in handy. You could dispatch an action (something like SELECT_CLASS) that sets the selected class in the store, then read that value from your new component. I'd recommend this approach.

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

However, there is another way. Each browser history entry has a concept of state. So, when you navigate to your new route, you can save the selected data in the state for that history entry, then read it when the component renders. It would look something like this:

保存状态:

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

阅读:

router.location.state

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

React router docs: https://github.com/ReactTraining/react-router/blob/master/docs/API.md#pushpathorloc

更新:是的 redux!首先,让我们为此定义动作 + 动作创建者:

UPDATE: Yay for redux! So first, lets define the action + action creator for this:

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

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

Now, lets take a look at what the reducer to handle this would look like:

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 连接了您的组件:

Now, assuming you've connected your components via react-redux like this:

// 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);

这是您设置所选类的方式:

This is how you'll set the selected class:

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

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

And in your next component (which should also be connected, but doesn't require mapDispatchToProps:

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

如果您需要任何帮助来设置 react + redux,文档这里 太棒了.如果我使用的 ES6 语法看起来不熟悉,可以参考 babel 文档这里

If you need any help setting up react + redux, the docs here are fantastic. If the ES6 syntax I used looks unfamiliar, a good reference are the babel docs here

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

UPDATE 2: I took your fiddle and ran with it: http://jsfiddle.net/k7wbzc4j/17/. Each button has a click event that will get the correct object.

最终更新:这是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.最后,我们确保找到了一个匹配的对象,然后做任何必要的事情来正确处理点击.这很混乱,但鉴于您的数据结构是必要的.我建议尝试更相关地存储这些数据并分别存储每种类型的项目(例如.UsersClassesDays、和 Schedules 对象都在单独的数组中,id 将它们链接在一起)

First, we use forEach to iterate over the array data that holds all of the schedules. Then, we iterate over each day (currently only monday and tuesday) to get all the classes on that day for the current schedule. Then, since we don't know the names of all the classes, we just grab all of the keys (which are the class names) and iterate over those. Finally, we can get the actual class objects and check if the classTitle matched the one that was clicked. If so, we save that object to obj. At the very end, we ensure that we found a matching object, then do whatever is necessary to properly handle that click. That's pretty messy, but necessary given your data structure. I'd recommend trying to store this data a bit more relationally and storing each type of item separately (eg. Users, Classes, Days, and Schedules objects all in separate arrays with ids linking them together)

为了解决您担心某些 classTitle 将相同的问题,您还必须弄清楚谁的日程被点击(可能是点击的那一天).您可以通过多种方式执行此操作:向每个按钮添加一个 data-user 属性并在单击时获取该属性,实现选定用户"的概念,创建一个新组件(可能称为 UserSchedule) 呈现该表中的一行,并将该用户的类作为道具.这样,您就会知道任何匹配的类都属于该用户.就像我说的:多种方式.

To address your concern that some classTitles will be the same, you'll have to also figure out who's schedule was clicked (and potentially the day that it was clicked). You could do this a number of ways: add a data-user attribute to each button and grab that on click, implement a concept of a "Selected User", create a new component (maybe called UserSchedule) that renders a row in that table and takes, as props, that user's classes. That way, you'll know that any class that matches belongs to that user. Like I said: a number of ways.

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

As for showing you how to pass that to a new component, I've demonstrated 2 ways above of how to do that above: through history state or storing the value in a redux reducer and receiving it as props. Doing any more would equate to me solving the entire problem for you, which I'm not going to do since the only way this stuff sticks is for you to do it yourself. Trust in yourself, follow the advice I've given, and use the internet for any specific bugs you're having and you'll come out on top!

这篇关于ReactJS + React Router:如何引用特定对象作为属性传递?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆