0

I am using redux and I am working on receiving data about membership information from action and processing it from components.

And try to process the data to a table.

I took data from user action and created a table through map functions... The incoming data contains

Data received as action ....

[{create_date : "2020-02-16T03:00:00Z", id:"test"},
{create_date : "2020-02-16T01:00:00Z", id:"test1"},
{create_date : "2020-02-14T03:00:00Z", id:"test2"},
{create_date : "2020-02-14T01:00:00Z", id:"test3"},
{create_date : "2020-02-14T00:00:01Z", id:"test4"},
{create_date : "2020-02-13T03:00:00Z", id:"test5"},
...] 

As you can see, only create_date id is included.

I would like to order them by date and number them in order by next day after day.

For example, would like to print like this.

index    create_date           id   
2        2020-02-16T03:00:00Z  test
1        2020-02-16T01:00:00Z  test1

3        2020-02-14T03:00:00Z  test2
2        2020-02-14T01:00:00Z  test3
1        2020-02-14T00:00:01Z  test4

1        2020-02-13T03:00:00Z  test5

How to insert index using if statement when using map function in react??

Mycode

    render() {
        const {user_list} = this.props;
        console.log(user_list);
        return (
            <div className="animated fadeIn">
                <Row>
                    <Col xl={12}>
                        <Card>
                            <CardHeader>
                                <i className="fa fa-align-justify"></i>userlist
                            </CardHeader>
                            <CardBody>
                                <Search searchUser={this.searchUser}/>
                                <Table responsive hover>
                                    <thead>
                                    <tr><th scope="col">Index</th>
                                        <th scope="col">create_time</th>
                                        <th scope="col">id/name</th>
                                    </tr>
                                    </thead>
                                    <tbody>
                                    {user_list.length > 0 && user_list.map((item, index) => (
                                        <tr key={item.id.toString()}>
                                            <td>{index}</td> //<<Does this change by date index.. if statement?
                                            <td className={'datetime'}>
                                                {item.hasOwnProperty('create_date') &&
                                                    <div>
                                                        {moment(item.create_date).format('YYYY-MM-DD')}<br/>
                                                        {moment(item.create_date).format('HH:mm')}
                                                    </div>
                                                }
                                            </td>
                                            <td scope="row">
                                                    {item.displayName}
                                            </td>

                                        </tr>
                                    ))}
                                    </tbody>
                                </Table>
                            </CardBody>
                        </Card>
                    </Col>
                </Row>


            </div>
        )
    }

....

hoon3024
  • 27
  • 5
  • Is the question how to sort, or how to render the index from `map`? It's not clear what you are asking here. – James Feb 16 '20 at 08:40
  • Is it possible for me to do the output I want with the data that I have less? from **map** – hoon3024 Feb 16 '20 at 08:47
  • not directly from `map`, unless you _pre sort_ the data, and not by leveraging the `index` from the array directly, you want to render a synthetic index here. [Group](https://stackoverflow.com/a/34890276/82586) your data, sort each group, then you can render each group and print the index as it'll be relative to the group. Worth considering a utility library like [lodash](https://lodash.com/), lots of useful functions including `groupBy`. – James Feb 16 '20 at 08:52
  • .map(item, index) {...} gives you access to the array item and that item’s index each iteration. So your index would be 0, 1, 2, 3, 4, 5 for your array. The “index” column you have created here is not the index of the array. Probably you should name it something else like “daily entries” or something. Is your action data always sorted (as shown)? Or does it need to be sorted? – Alex L Feb 16 '20 at 08:54
  • @AlexL action data is always sorted recive. So what's the best way to give index and build a table as I intended? – hoon3024 Feb 16 '20 at 09:02
  • check out my answer and my codePen https://codepen.io/Alexander9111/pen/rNVeyyY – Alex L Feb 16 '20 at 09:55

2 Answers2

2

Elaborate on comments of @James. I just changed a little bit.

You can group them first by date. And then flat it to a list you want. Plain javascirpt version:

let data = [{create_date : "2020-02-16T03:00:00Z", id:"test"},
{create_date : "2020-02-16T01:00:00Z", id:"test1"},
{create_date : "2020-02-14T03:00:00Z", id:"test2"},
{create_date : "2020-02-14T01:00:00Z", id:"test3"},
{create_date : "2020-02-14T00:00:01Z", id:"test4"},
{create_date : "2020-02-13T03:00:00Z", id:"test5"},
]

let groups = {}
for (let e of data.reverse()) {
  let date = e.create_date.slice(0, 10)
  if (groups[date]) {
    let group = groups[date];
    group.push({ index: group.length + 1, ...e });
  } else {
    groups[date] = [{ index: 1, ...e }]
  }
}

const dates = Object.keys(groups).reverse()
const flatten = []
for (let date of dates) {
  flatten.push(...(groups[date].reverse()))
}

console.log(flatten)

flatten should be logged as:

[ { index: 2, create_date: '2020-02-16T03:00:00Z', id: 'test' },
  { index: 1, create_date: '2020-02-16T01:00:00Z', id: 'test1' },
  { index: 3, create_date: '2020-02-14T03:00:00Z', id: 'test2' },
  { index: 2, create_date: '2020-02-14T01:00:00Z', id: 'test3' },
  { index: 1, create_date: '2020-02-14T00:00:01Z', id: 'test4' },
  { index: 1, create_date: '2020-02-13T03:00:00Z', id: 'test5' } ]

You should be able to render that directly in a map. Though I think it's better to store the flatten list as state or in redux store so that it won't do the transformation on every rerender.

bedew
  • 118
  • 1
  • 1
  • 6
2

Here's a minimal verifiable complete working demo (https://codepen.io/Alexander9111/pen/rNVeyyY), taking part of the excellent grouping and flattening function from @bedew and then sorting it into date and "index" to give the following output (in React CodePen):

enter image description here

JS:

const action_data = [
  {create_date : "2020-02-16T03:00:00Z", id:"test"},
  {create_date : "2020-02-16T01:00:00Z", id:"test1"},
  {create_date : "2020-02-14T03:00:00Z", id:"test2"},
  {create_date : "2020-02-14T01:00:00Z", id:"test3"},
  {create_date : "2020-02-14T00:00:01Z", id:"test4"},
  {create_date : "2020-02-13T03:00:00Z", id:"test5"}
];

const Demo = (props) => {
  console.log(props.action)

  let groups = {}
  for (let e of props.action.reverse()) {
    let date = e.create_date.slice(0, 10)
    if (groups[date]) {
      let group = groups[date];
      group.push({ index: group.length + 1, ...e });
    } else {
      groups[date] = [{ index: 1, ...e }]
    }
  }

  const dates = Object.keys(groups).reverse()
  const flatten = []
  for (let date of dates) {
    flatten.push(...(groups[date].reverse()))
  }
  const user_list = flatten.sort((a,b) => {
    if (moment(b.create_date).diff(moment(a.create_date), 'days') == 0){
      return (b.index - a.index);
    } else {
      return 0;
    }      
  });
  console.log(user_list);

  return(
    <div>
    <table>
      <thead>
        <tr>
          <th scope="col">Index</th>
          <th scope="col">create_time</th>
          <th scope="col">id/name</th>
        </tr>
      </thead>
      <tbody>
        {user_list.length > 0 && user_list.map((item, index) => (
          <tr key={item.id.toString()}>
            <td>{item.index}</td>
            <td className={'datetime'}>
              {item.hasOwnProperty('create_date') &&
                <div>
                  {moment(item.create_date).format('YYYY-MM-DD') + "  "+ moment(item.create_date).format('HH:mm')}
                </div>
              }
            </td>
            <td scope="row">
              {item.id}
            </td>
          </tr>
        ))}
      </tbody>
    </table>
    </div>
  )
}

ReactDOM.render(
  <Demo action={action_data}/>,
  document.getElementById('root')
);

Important is the sort function:

const user_list = flatten.sort((a,b) => {
    if (moment(b.create_date).diff(moment(a.create_date), 'days') == 0){
      return (b.index - a.index);
    } else {
      return 0;
    }      
  });

If the dates are not the same day, then don't sort, but if they are the same day then sort on the "index" created in the flatten array earlier.

Again demo here: https://codepen.io/Alexander9111/pen/rNVeyyY

Alex L
  • 4,168
  • 1
  • 9
  • 24