2

I'm building an ERP-style app using MERN and Redux. My backend is working well, I can add things through my API and all, but I'm having some stupid issues with my front-end.

The idea is that I have item-objects and want to access them through a modal. The modal itself works, and the button used to open the modal actually gets the names of the objects through the loop.

The issue comes in inside the ModalBody - it only fetches the information from the first object in the table. I've tried methods such as this.props.customer, items.customer, this.items.customer and many, many more without success.

It would be cool if I can export the component as a class too, but if it's impossible, that's okay I guess.

Do you guys have any idea on how I can make it work?

render(){
  const { items } = this.props.item;

  return (
    <Container>
      <ListGroup>
        <TransitionGroup className="shopping-list">
          {items.map(({ _id, name, customer, location, dilemma }) =>
            <CSSTransition key={_id} timeout={500} classNames="fade">
              <ListGroupItem key={_id}>
                <Button color="light" style={{ width: "100%" }} onClick={this.toggle}>{name}</Button>
                <Modal isOpen={this.state.modal} toggle={this.toggle}>
                  <ModalHeader toggle={this.toggle} key={_id}>{name}</ModalHeader>
                  <ModalBody key={index}>
                    <p>Customer: {customer}</p>
                    <p>Location: {location}</p>
                    <p>Dilemma: {dilemma}</p>
                  </ModalBody>
                </Modal>
              </ListGroupItem>
            </CSSTransition>
          )}
        </TransitionGroup>
      </ListGroup>
    </Container>
  );
}

3 Answers 3

4

You don't need to generate a modal for every item. Just list items and create one modal. After that, when an item clicked pass the related item to modal and set visible.

I create a mini sample for you.

import React, { Component } from 'react';
import { render } from 'react-dom';

const Modal = (props) => {
  return (
    props.visible ? (
      <div>
        Product info
        <hr />
        <h3>{props.item.name}</h3>
      </div>
    ) : ""
  )
}

class App extends Component {
  constructor() {
    super();
    this.state = {
      selectedItem: null,
      modalState: false
    };
  }

  data = [{
    id: 1,
    name: "p1"
  }, {
    id: 2,
    name: "p2"
  }, {
    id: 3,
    name: "p3"
  },
  ]

  handleItemClick = (id) => {
    this.setState({
      modalState: true,
      selectedItem: this.data.find(a => a.id === id)
    })
  }

  render() {
    const { modalState, selectedItem } = this.state

    const mappedList = this.data.map(
      (i) => (
        <li key={i.id} onClick={() => this.handleItemClick(i.id)}>{i.name}</li>
      )
    );

    return (
      <div>
        <ul>{mappedList}</ul>
        <Modal visible={modalState} item={selectedItem} />
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

https://stackblitz.com/edit/react-gheoek

Sign up to request clarification or add additional context in comments.

2 Comments

So after 3 sprints where I spent lots of time trying to make my old setup to work, I just decided to create a whole new Component and am getting good results with your example as a draft. Thank you very much, the world will soon have yet another crappy inventory system haha!
@Sylvio, Ohh no, I created a monster! :)
3

I am not sure I get what is your intention, but I would pass the items array to the Modal component as prop, then use map in the Modal component AFTER the ModalBody. The way you are doing now you are rendering a lot of stuff (including Modal) for every item in the itemsarray.

Comments

2

I'm not sure how your array looks like but have you tried using the map() like this?

{
  items.map((item, key) =>
    <CSSTransition key={key} timeout={500} classNames="fade">
      <ListGroupItem key={item._id}>
        <Button color="light" style={{ width: "100%" }} onClick={this.toggle}>{item.name}</Button>
        <Modal isOpen={this.state.modal} toggle={this.toggle}>
          <ModalHeader toggle={this.toggle} key={item._id}>{item.name}</ModalHeader>
          <ModalBody key={key}>
            <p>Customer: {item.customer}</p>
            <p>Location: {item.location}</p>
            <p>Dilemma: {item.dilemma}</p>
          </ModalBody>
        </Modal>
      </ListGroupItem>
    </CSSTransition>
  )
}

Also are you looking to render all items from the array in one specific modal or would you like to fill up one modal with an item from the array? In the last case it would be better to render just one modal and pass the item props for that specific item to the modal.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.