Как удалить объект на основе его индекса из вложенного массива в React? - PullRequest
1 голос
/ 18 июня 2019

Я нажимаю значок «Удалить» на товаре. Я вытаскиваю его индекс и сохраняю его в состоянии. Пример: select: 1, index: 1. Как установить this.setState для удаления объекта, вложенного в массив colors в массиве products. Пример удаления объекта:

{
  a: 'orange'
} 

из массива colors в массиве products

this.state.select - это элемент в продуктах, this.state.index - это цвет в элементе, который нужно удалить

А как это выглядит в реальном приложении? Дайте ваши продукты и цвета id? Я хотел бы, чтобы это было динамичным. Я нажимаю на товар, скачиваю его индекс и удаляю

class App extends Component {
  constructor(){
    super();

    this.state {
      products: [  
            {
                colors: [{a:'black'}, {a:'orange'}, {a:'purple'}]
                desc: 'gfgfg'
            },
            {
                colors: [{a: 'yellow'}, {a: 'white'}, {a:'gray'}],
                desc: 'gfgfgfg'
            },
            {
                colors: [{a: 'pink'}, {a: 'brown'}, {a:'green'}],
                desc: 'gfgfgfg'
            }
        ],
        select: 1 //example
        index: 1 //example
    }

  }

  removeItem = () => {
    const { select, index } = this.state;

    if(index) {
      this.setState({
          products: [
            ...this.state.products[select].colors.slice(0, index),
            ...this.state.products[select].colors.slice(index + 1),
          ]
      });
    }
  };


  render () {

    return (
      <div>
        <ul>
            {
                this.state.products
                .map((product, index) =>
                    <Product
                        key={index}
                        index={index}
                        product={product}
                    />
                )
            }
        </ul>
          <Products

          />
      </div>
    )
  } 
}

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Необходимо передать функцию удаления компоненту Product, в компоненте Product передать выбор и индексировать функции removeItem.

измените удаляемый элемент, чтобы получить два параметра, select и index.

removeItem = (select, index) => {

  const filtered = this.state.products[select].colors.filter(
    (color, i) => i !== index
  );

  this.setState(prevState => {
    return {
      select: select,
      index: index,
      products: [
        ...prevState.products.slice(0, select),
        Object.assign({}, prevState.products[select], { colors: filtered }),
        ...prevState.products.slice(select + 1)
      ]
    };
  });
};

Передать функцию в качестве опоры компоненту Product.

<div>
  <ul>
    {this.state.products.map((product, index) => (
      <Product
        key={index}
        index={index}
        removeItem={this.removeItem}
        product={product}
      />
    ))}
  </ul>
</div>

В компоненте вашего продукта передайте индекс цвета и выберите.

<button onClick={() => removeItem(index, i)}>X</button>

DEMO

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>

<div id="root"></div>

<script type="text/babel">

class Product extends React.Component {
  render() {
    const { product, removeItem, index } = this.props;
    return (
      <div>
        <p>{product.desc}</p>
        <ul>
          {product.colors.map((color, i) => (
            <li>
              {color.a} <button onClick={() => removeItem(index, i)}>X</button>
            </li>
          ))}
        </ul>
      </div>
    );
  }
}

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "React",
      products: [
        {
          colors: [{ a: "black" }, { a: "orange" }, { a: "purple" }],
          desc: "gfgfg"
        },
        {
          colors: [{ a: "yellow" }, { a: "white" }, { a: "gray" }],
          desc: "gfgfgfg"
        },
        {
          colors: [{ a: "pink" }, { a: "brown" }, { a: "green" }],
          desc: "gfgfgfg"
        }
      ],
      select: 1, //example
      index: 1 //example
    };
  }

    removeItem = (select, index) => {
      const filtered = this.state.products[select].colors.filter(
        (color, i) => i !== index
      );

      this.setState(prevState => {
        return {
          select: select,
          index: index,
          products: [
            ...prevState.products.slice(0, select),
            Object.assign({}, prevState.products[select], { colors: filtered }),
            ...prevState.products.slice(select + 1)
          ]
        };
      });
    };

  render() {
    return (
    <div>
      <ul>
        {this.state.products.map((product, index) => (
          <Product
            key={index}
            index={index}
            removeItem={this.removeItem}
            product={product}
          />
        ))}
      </ul>
    </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
</script>
0 голосов
/ 18 июня 2019

Просто используйте Array.filter(), чтобы создать новый массив, не содержащий определенного элемента.Итак, ваш новый массив цветов для этого desc:

this.state.products[select].colors.filter( color => color.a !== 'orange' )

При этом сохраняются все цвета, где a не оранжевый.Имейте в виду, что массивы начинаются с нуля, поэтому ваши select и index должны начинаться с 0.

Если вы не хотите хранить фактические индексы, используйте вместо них desc.

Так что если select будет gfgfg вместо индекса массива, вы можете сделать:

const state = {
  products: [
      {
          colors: [{a:'black'}, {a:'orange'}, {a:'purple'}],
          desc: 'gfgfg'
      },
      {
          colors: [{a: 'yellow'}, {a: 'white'}, {a:'gray'}],
          desc: 'gfgfgfg'
      },
      {
          colors: [{a: 'pink'}, {a: 'brown'}, {a:'green'}],
          desc: 'gfgfgfg'
      }
  ],
  selected_product: 'gfgfg',
  color: 'orange'
};

const setState = update => Object.assign( state, update );

console.log( 'before update' );
console.log( JSON.stringify( state.products[0] ));

setState({
  products: state.products.map( product => {
    if ( product.desc === state.selected_product ) {
      product.colors = product.colors.filter( color => color.a !== state.color );
    }
    return product;
  })
});

console.log( 'after update' );
console.log( JSON.stringify( state.products[0] ));

Та же логика, очевидно, может быть выполнена с использованием индексов, но это может привести к увеличению длины кода.Возможно, придется обновить часть кода, если все должно быть полностью неизменным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...