Как переключить отдельный элемент из итерации вложенной карты в реакции - PullRequest
0 голосов
/ 15 февраля 2020

Я новичок, чтобы реагировать. Я работаю над проектом по созданию сменной роты для рабочих. Создана сетка с ячейками. Когда вы щелкаете по ячейке, она меняет свое значение с номера дня на «Выходной», а если вы щелкнете ее снова, она вернется к номеру дня. Проблема в том, что когда я щелкаю ячейку, целые строки ячеек меняют свои значения. Что делать, чтобы изменить значение только одной ячейки?

Это мой код ...

export default class DayNames extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isToggleOn: true
    };
  }

  handleClick = e => {
    this.setState(prevState => ({
      isToggleOn: { ...prevState.isToggleOn, [e]: !prevState.isToggleOn[e] }
    }));
  };

  render() {
    //Getting number of days of month
    const month = new Date().getMonth() + 1;
    const year = new Date().getFullYear();
    const numberDaysOfMonth = new Date(year, month, 0).getDate();

    let foo1 = [];
    for (let i = 1; i <= numberDaysOfMonth; i++) {
      foo1.push(i);
    }

    let foo2 = ["Ops1", "Ops2", "Ops3", "Ops4", "Ops5", "Ops6"];
    const ops = foo2.map((elem, index) => {
      return (
        <div className="ops_header" key={index}>
          {elem}
          {foo1.map((cell, i) => {
            return (
              <div
                className="operator"
                data-id={cell}
                key={i}
                onClick={() => this.handleClick(i)}
              >
                {this.state.isToggleOn[i] ? "Holiday" : cell}
              </div>
            );
          })}
        </div>
      );
    });

    return (
      <div>
        <div className="table">{ops}</div>
      </div>
    );
  }
}

Это ссылка на песочницу ... / components / DayNames / DayNames. js https://codesandbox.io/s/react-toggle-day-0rjop

Ответы [ 3 ]

0 голосов
/ 15 февраля 2020

Есть много способов сделать это, в моем решении я использовал Set, что дает O(1) сложность при настройке, добавлении и удалении переключаемых дней, а это именно то, что вам нужно:

import React, { Component } from "react";
import "./DayNames.css";

export default class DayNames extends Component {
  constructor(props) {
    super(props);
    this.state = {
      bgColor: "lightslategrey",
      toggledDays: new Set()
    };
  }

  createDayId = (columnIndex, rowIndex) => `${columnIndex}-${rowIndex}`;

  handleClick = (columnIndex, rowIndex) => {
    this.setState(prevState => {
      const prevToggledDays = prevState.toggledDays;
      const dayId = this.createDayId(columnIndex, rowIndex);
      if (this.isDayToggled(columnIndex, rowIndex)) {
        prevToggledDays.delete(dayId);
      } else {
        prevToggledDays.add(dayId);
      }
      return { toggledDays: prevToggledDays };
    });
  };

  isDayToggled = (columnIndex, rowIndex) => {
    const dayId = this.createDayId(columnIndex, rowIndex);
    return this.state.toggledDays.has(dayId);
  };

  render() {
    //Getting number of days of month
    const month = new Date().getMonth() + 1;
    const year = new Date().getFullYear();
    const numberDaysOfMonth = new Date(year, month, 0).getDate();

    let foo1 = [];
    for (let i = 1; i <= numberDaysOfMonth; i++) {
      foo1.push(i);
    }

    let foo2 = ["Ops1", "Ops2", "Ops3", "Ops4", "Ops5", "Ops6"];
    const ops = foo2.map((elem, columnIndex) => {
      return (
        <div className="ops_header" key={columnIndex}>
          {elem}
          {foo1.map((cell, rowIndex) => {
            return (
              <div
                className="operator"
                data-id={cell}
                key={rowIndex}
                onClick={() => this.handleClick(columnIndex, rowIndex)}
              >
                {this.isDayToggled(columnIndex, rowIndex) ? "Holiday" : cell}
              </div>
            );
          })}
        </div>
      );
    });

    return (
      <div>
        <div className="table">{ops}</div>
      </div>
    );
  }
}

И все же иногда опасно ретранслировать индексы, но в вашем случае это кажется подходящим

Надеюсь, это поможет <3 </p>

0 голосов
/ 15 февраля 2020

Похоже, что когда вы включали, получали все индексы для ячейки, я добавил еще один параметр, который в основном является индексом вашего foo2, и изменил условие переключения с одного индекса на оба [i = foo1, i = foo2];

// This line changed from e => (e,index)
handleClick = (e, index) => {
// memories both index and put into one variable
    const target = [e, index];
    console.log(target);
    this.setState(prevState => ({
// update state
      isToggleOn: { ...prevState.isToggleOn, [target]: !prevState.isToggleOn[target] }
    }));
};
    let foo2 = ["Ops1", "Ops2", "Ops3", "Ops4", "Ops5", "Ops6"];
    const ops = foo2.map((elem, index) => {
      return (
        <div className="ops_header" key={index}>
          {elem}
          {foo1.map((cell, i) => {
            return (
              <div
                className="operator"
                data-id={cell}
                key={i}
                // pass both indexes to handleClick();
                onClick={() => this.handleClick(i, index)}
              >
                // togle based on indexes;
                {this.state.isToggleOn[[i, index]] ? "Holiday" : cell}
              </div>
            );
          })}
        </div>
      );
    });
0 голосов
/ 15 февраля 2020

Попробуйте этот код песочница нажмите здесь

Или посмотрите ниже обновленный компонент.

import React, { Component } from "react";
import "./DayNames.css";

export default class DayNames extends Component {
  foo2 = ["Ops1", "Ops2", "Ops3", "Ops4", "Ops5", "Ops6"];

  constructor(props) {
    super(props);
    const month = new Date().getMonth() + 1;
    const year = new Date().getFullYear();

    this.state = {
      bgColor: "lightslategrey",
      // isToggleOn: true,
      days: Array(this.foo2.length)
        .fill(0)
        .map(x => Array(new Date(year, month, 0).getDate()).fill(0))
    };
  }

  handleClick = (index, i) => {
    const { days } = this.state;
    days[index][i] = !days[index][i];
    this.setState({
      days
    });
  };

  render() {
    //Getting number of days of month
    const month = new Date().getMonth() + 1;
    const year = new Date().getFullYear();
    const numberDaysOfMonth = new Date(year, month, 0).getDate();

    let foo1 = [];
    for (let i = 1; i <= numberDaysOfMonth; i++) {
      foo1.push(i);
    }

    const ops = this.foo2.map((elem, index) => {
      return (
        <div className="ops_header" key={index}>
          {elem}
          {foo1.map((cell, i) => {
            return (
              <div
                className="operator"
                data-id={cell}
                key={i}
                onClick={() => this.handleClick(index, i)}
              >
                {this.state.days[index][i] ? "Holiday" : cell}
              </div>
            );
          })}
        </div>
      );
    });

    return (
      <div>
        <div className="table">{ops}</div>
      </div>
    );
  }
}

Я обновил код, ошибка была в том, что вы не были сохраняя каждое состояние клетки. Я исправил. Проверьте дней в состоянии.

...