Переключить элемент в массиве реагировать - PullRequest
0 голосов
/ 23 января 2019

Я хочу, чтобы переключить свойство объекта в массиве. Массив выглядит следующим образом. Это используется в компоненте реакции, и когда пользователь нажимает кнопку, я хочу переключить победителя.

const initialFixtures = [{
    teams: {
      home: 'Liverpool',
      away: 'Manchester Utd'
    },
    winner: 'Liverpool'
  },
  {
    teams: {
      home: 'Chelsea',
      away: 'Fulham'
    },
    winner: 'Fulham'
  }, ,
  {
    teams: {
      home: 'Arsenal',
      away: 'Tottenham'
    },
    winner: 'Arsenal'
  }
];

Мой код реакции выглядит примерно так

function Parent = () => {

  const [fixtures, setUpdateFixtures] = useState(initialFixtures)
  const toggleWinner = (index) => {
     const updatedFixtures = fixtures.map((fixture, i) => {
           if (i === index) {
                return {
                    ...fixture,
                    winner: fixture.winner === home ? away : home,
                };
            } else {
                return fixture;
            }
     }) 
     setUpdateFixtures(updatedFixtures);
  }

  return <Fixtures fixtures={fixtures} toggleWinner={toggleWinner} />;

}


function Fixtures = ({ fixtures, toggleWinner }) => { 
  fixtures.map((fixture, index) => ( 
    <div>
        <p>{fixture.winner} </p>
    <button onClick = {() => toggleWinner(index)}> Change Winner</button> 
    </div>
  ))
}

код работает, но кажется, что это слишком много. Я уверен, что есть лучший, более лаконичный способ сделать это. Кто-нибудь может посоветовать? Мне нужно передать приборы от родителя компонента Fixture по архитектурным соображениям.

Ответы [ 6 ]

0 голосов
/ 23 января 2019

Если вам удобно использовать подход на основе классов, вы можете попробовать что-то вроде этого:

  • Создайте класс, который содержит значение свойства для команды.
  • Создайте логическое свойствов этом классе, скажем isHomeWinner.Это свойство определит победителя.
  • Затем создайте свойство получателя winner, которое будет искать this.isHomeWinner и даст необходимое значение.
  • Это позволит вам получить чистую toggleфункция: this.isHomeWinner = !this.isHomeWinner.

Вы также можете написать свой toggleWinner как:

const toggleWinner = (index) => {
  const newArr = initialFixtures.slice();
  newArr[index].toggle();
  return newArr;
};

Это выглядит чисто и декларативно.Обратите внимание, что если неизменность необходима, то требуется только это.Если вам удобны изменяющиеся значения, просто передайте fixture.toggle вашему компоненту реакции.Вам может потребоваться привязать контекст, но это также должно работать.

Так что это будет выглядеть примерно так:

function Fixtures = ({ fixtures, toggleWinner }) => { 
  fixtures.map((fixture, index) => ( 
    <div>
      <p>{fixture.winner} </p>
      <button onClick = {() => fixture.toggle() }> Change Winner</button> 

      // or
      // <button onClick = { fixture.toggle.bind(fixture) }> Change Winner</button> 
    </div>
  ))
}

Ниже приведен пример класса и его использования:

class Fixtures {
  constructor(home, away, isHomeWinner) {
    this.team = {
      home,
      away
    };
    this.isHomeWinner = isHomeWinner === undefined ? true : isHomeWinner;
  }

  get winner() {
    return this.isHomeWinner ? this.team.home : this.team.away;
  }

  toggle() {
    this.isHomeWinner = !this.isHomeWinner
  }
}

let initialFixtures = [
  new Fixtures('Liverpool', 'Manchester Utd'),
  new Fixtures('Chelsea', 'Fulham', false),
  new Fixtures('Arsenal', 'Tottenham'),
];

const toggleWinner = (index) => {
  const newArr = initialFixtures.slice();
  newArr[index].toggle();
  return newArr;
};

initialFixtures.forEach((fixture) => console.log(fixture.winner))
console.log('----------------')
initialFixtures = toggleWinner(1);
initialFixtures.forEach((fixture) => console.log(fixture.winner))

initialFixtures = toggleWinner(2);
console.log('----------------')
initialFixtures.forEach((fixture) => console.log(fixture.winner))
0 голосов
/ 23 января 2019

если вы напишите свой код таким образом - это сделает работу.

const toggleWinner = index => {
    const { winner, teams: { home, away } } = fixtures[index];
    fixtures[index].winner = winner === home ? away : home;

    setUpdateFixtures([...fixtures]);
};

Установка нового массива приборов в состояние полностью достаточна для запуска render на Fixtures компоненте.

Я сделал рабочий пример для вас.

0 голосов
/ 23 января 2019

Вы можете нарезать массив приборов на три части:

  • от 0 до index: fixtures.slice(0, index).Эта часть перемещена в новый массив без изменений.

  • Одиночный элемент в index.Эта часть / элемент выбрасывается из-за изменения и заменяется новый элемент.

  • Остальная часть массива: fixtures.slice(index + 1).

Затем поместите их в новый массив:

const newFixtures = [
    ...fixtures.slice(0, index),    // part 1
    {/* new item at 'index' */},    // part 2
    ...fixtures.slice(index + 1)    // part 3
];

Для создания нового элемента:

0 голосов
/ 23 января 2019
const updatedFixtures = [...fixtures];
const fixture = updatedFixtures[i];
updatedFixtures[i] = {
  ...fixture,
  winner: fixture.winner === fixture.teams.home ? fixture.teams.away : fixture.teams.home,
};
0 голосов
/ 23 января 2019

Вы можете использовать библиотеки, такие как immer, для простого обновления вложенных состояний.

const initialFixtures = [{
    teams: {
      home: 'Liverpool',
      away: 'Manchester Utd'
    },
    winner: 'Liverpool'
  },
  {
    teams: {
      home: 'Chelsea',
      away: 'Fulham'
    },
    winner: 'Fulham'
  }, ,
  {
    teams: {
      home: 'Arsenal',
      away: 'Tottenham'
    },
    winner: 'Arsenal'
  }
];

const newState = immer.default(initialFixtures, draft => {
  draft[1].winner = "something";
});

console.log(newState);
<script src="https://cdn.jsdelivr.net/npm/immer@1.0.1/dist/immer.umd.js"></script>
0 голосов
/ 23 января 2019
      const toggleWinner = (index) => {
        let  updatedFixtures = [...fixtures].splice(index, 1, {...fixtures[index],
         winner: fixtures[index].winner === fixtures[index].teams.home
         ? fixtures[index].teams.away : fixtures[index].teams.home})

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