наиболее эффективный способ обновить свойство свойства в Javascript объекте для ловушек React - PullRequest
0 голосов
/ 30 марта 2020

У меня есть следующий объект в useState:

const [obj, setObj] = React.useState({ 
       one: {
          index: "one",
          name: "Number one"
       },
       two: {
          index: "two",
          name: "Number two"
       }
    });

Я хочу обновить index или name за один вызов. У меня есть это:

function update(from, what, value) {
   const objTemp = {...obj};
   obj[from][what] = value;
   setObj(objTemp);
}

Я вызываю эту функцию как: update('one', 'index', 'Hey') или update('two', 'name', 'Foo'). Я пытался и могу справиться с этим сценарием:

const [x, setX] = React.useState({ one: 'One', two: 'Two' });

function updt(from, value) {
   setX({...x, [from]: value});
}

Но я не смог найти способ оптимизировать мою первую функцию, как последнюю. Я попытался:

setObj({...obj, [from][what]: value});

Но это точно не сработало. Есть ли способ оптимизировать мою функцию update так, чтобы она выглядела как моя функция updt?

Ответы [ 2 ]

1 голос
/ 30 марта 2020

со сложным состоянием, подобным этому, вы не должны использовать State, просто попробуйте useReducer

const initialState = { 
       one: {
          index: "one",
          name: "Number one"
       },
       two: {
          index: "two",
          name: "Number two"
       }
    };

function reducer(state, action) {
  switch (action.type) {
    case 'update':
      const { property, subProperty, value } = actions.payload
      const newState = {
        ...state,
        [property]: {
          ...state[property],
          [subProperty]: value
        }
      }
      return newState;
    default:
      throw new Error();
  }
}

, тогда вы можете использовать его с

dispatch({type: 'update', payload: {"one", "name", "Number 1"})
1 голос
/ 30 марта 2020

Вы близки, по сути, вам нужен второй объект, расширяющий / видоизменяющий вложенный объект, который вы обновляете.

setObj({...obj, [from]: { ...obj[from], [what]: value} });

Примечание: Вы все еще копируете все целиком объект, то есть каждое неисчислимое свойство, так что это технически столь же эффективно (с точки зрения Big-O), что и то, что у вас уже есть / было. ( Может быть, даже немного меньше, так как сейчас две операции распространения !! )

Можно также утверждать, что теперь оно немного менее читаемо, сейчас сводится к одной строке.

Важным шагом для обновления состояния реакции является чистая парадигма функции всегда возвращать новые ссылки на объекты, что является причиной начального распространения объекта.

Следует также отметить, что не рекомендуется хранить сложные объекты в useState хуках по этой самой причине , поддержание корректного обновления состояния с помощью глубоко вложенных обновлений - это гораздо больше работы. useReducer обычно рекомендуется для этих ситуаций. Та же сложность обновления существует, но это более четкий шаблон.

const obj = {
  one: {
    index: "one",
    name: "Number one"
  },
  two: {
    index: "two",
    name: "Number two"
  }
};

function update(from, what, value) {
  return {...obj, [from]: { ...obj[from], [what]: value} };
}

console.log(update('one', 'name', 'Number 1'))
...