tom harrison
tom harrison

Reputation: 3433

remove placeholder when item is added to array React

I have 5 positions with a number placeholder available for items that are added to an array to appear, the problem is I need these numbered placeholders to dissapear once the item has been added to the array.

How can I remove the numbered placeholders when the item is added to the array?

https://codesandbox.io/s/qlp47q8j26

Hello.js

import React from 'react';
import update from 'immutability-helper'
import styled from 'styled-components'
import Product from './Product'

const NumberWrap = styled.div`
  display: flex;
  flex-wrap:wrap
  border: 1px solid #ccc;
  flex-direction: row;
`

const Numbers = styled.div`
  display:flex;
  background: #fafafa;
  color: #808080;
  font-size: 32px;
  flex: 0 0 20%;
  min-height: 200px;
  justify-content: center;
  align-items:center;
  border-right: 1px solid #ccc;
`

const CardWrap = styled.div`
  display:flex;
  flex-wrap: wrap;
  flex-direction: row;
  margin-top: 20px;
`

export default class Hello extends React.Component {
  constructor() {
    super()
    this.state = {
      placeholder: [1,2,3,4,5],
      data: [
        { id: 1, header: 'Item 1'},
        { id: 2, header: 'Item 2'},
        { id: 3, header: 'Item 3'},
        { id: 4, header: 'Item 4'}
      ],
      addedItems: [],
    }
  }

  handleAdd = (id) => {
    this.setState({
        addedItems: update(this.state.addedItems, {
        $push: [
          id,
        ],
      })
    })
  }

  handleRemove = (id) => {
    const index = this.state.addedItems.indexOf(id);
    this.setState({
      addedItems: update(this.state.addedItems, {
        $splice: [
          [index, 1]
        ],
      })
    })
  }

  render() {
    return(
      <div>
        <NumberWrap>
          {
            this.state.placeholder.map(num =>
              <Numbers>{num}
              {
                this.state.data.filter(item => {
                  return this.state.addedItems.indexOf(item.id) === num - 1;
                }).slice(0, 5).map(item =>
                  <Product {...item} remove={() => { this.handleRemove(item.id) }} />
                )
              } 
              </Numbers>
            )
          }
        </NumberWrap>


        <CardWrap>
        {
          this.state.data.map(item =>
            <Product
              {...item}
              add={()=> {
                this.handleAdd(item.id) 
              }}
            />
          )}   
        </CardWrap>
      </div>
    )
  }
}

Product.js

import React from "react";
import styled from "styled-components";

const Card = styled.div`
  flex: 0 0 20%;
  border: 1px solid #ccc;
`;

const Header = styled.div`
  padding: 20px;
`;

const AddBtn = styled.button`
  width:100%;
  height: 45px;
`;

const Product = props => {
  const { add, id, header, remove } = props;
  return (
    <Card>
      <Header key={id}>
        {header}
      </Header>
      <AddBtn onClick={add}>Add</AddBtn>
      <AddBtn onClick={remove}>Remove</AddBtn>
    </Card>
  );
};

export default Product;

Upvotes: 0

Views: 55

Answers (1)

Sagiv b.g
Sagiv b.g

Reputation: 31024

You should add an array of added Numbers to your state and render the number only if it's not exists in this array.

  1. I've added addedArray to the state in the constructor.
  2. Modified handleAdd and handleRemove to remove and add items to the new array.

  3. Added a condition to render the {num} in render method.

This is the modified code for Hello.js component:

import React from 'react';
import update from 'immutability-helper'
import styled from 'styled-components'
import Product from './Product'

const NumberWrap = styled.div`
  display: flex;
  flex-wrap:wrap
  border: 1px solid #ccc;
  flex-direction: row;
`

const Numbers = styled.div`
  display:flex;
  background: #fafafa;
  color: #808080;
  font-size: 32px;
  flex: 0 0 20%;
  min-height: 200px;
  justify-content: center;
  align-items:center;
  border-right: 1px solid #ccc;
`

const CardWrap = styled.div`
  display:flex;
  flex-wrap: wrap;
  flex-direction: row;
  margin-top: 20px;
`

export default class Hello extends React.Component {
  constructor() {
    super()
    this.state = {
      placeholder: [1,2,3,4,5],
      addedArray: [],
      data: [
        { id: 1, header: 'Item 1'},
        { id: 2, header: 'Item 2'},
        { id: 3, header: 'Item 3'},
        { id: 4, header: 'Item 4'}
      ],
      addedItems: [],
    }
  }

  handleAdd = (id) => {
    const nextAdded = [id,...this.state.addedArray];
    this.setState({
        addedArray: nextAdded,
        addedItems: update(this.state.addedItems, {
        $push: [
          id,
        ],
      })
    })
  }

  handleRemove = (id) => {
    const index = this.state.addedItems.indexOf(id);
    const nextAdded = this.state.addedArray.filter(n => n != id);
    this.setState({
      addedArray: nextAdded,
      addedItems: update(this.state.addedItems, {
        $splice: [
          [index, 1]
        ],
      })
    })
  }

  render() {
    return(
      <div>
        <NumberWrap>
          {
            this.state.placeholder.map(num =>
              <Numbers>
              {this.state.addedArray.filter(n=> n ==num).length == 0 && num}
              {
                this.state.data.filter(item => {
                  return this.state.addedItems.indexOf(item.id) === num - 1;
                }).slice(0, 5).map(item =>
                  <Product {...item} remove={() => { this.handleRemove(item.id) }} />
                )
              } 
              </Numbers>
            )
          }
        </NumberWrap>


        <CardWrap>
        {
          this.state.data.map(item =>
            <Product
              {...item}
              add={()=> {
                this.handleAdd(item.id) 
              }}
            />
          )}   
        </CardWrap>
      </div>
    )
  }
}

Upvotes: 1

Related Questions