Как динамически создавать объекты в состоянии с реагирующими хуками? - PullRequest
0 голосов
/ 20 февраля 2019

до сих пор в моем коде у меня был объект, который представлял бы все данные для изображения на странице

this.state = {
    img-1: {
        x: 0,
        y: 0,
        rotation: 0
    },
    img-2: {
        x: 20,
        y: 200,
        rotation: 50
    }
}

каждый раз, когда объект получает нового потомка, он добавляет новый img-id ксостояние, которое обновляется каждый раз, когда <img id=${id} update={this.update} /> обновляется.

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

Насколько я понимаю, мне нужно будет установить либо новый

[img-1, setImg-1] = useState({ x: 0, y:0, rotation: 0 })

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

[images, setImages] = useState({
    img-1: {
        x: 0,
        y: 0,
        rotation: 0
    }
})

const createImg = (newImg) => { setImages({...images, newImg}) }

const updateImg = (id, updatedImg) => {
    setImages({ ...images, [`img-${id}`]{...updatedImg} }
)}

Есть ли более чистый / более читаемый подход или мне просто нужно прибегнуть к вложению всего в один объект

1 Ответ

0 голосов
/ 20 февраля 2019

Вместо использования useState вы можете использовать useReducer, лучше контролировать свои состояния и обрабатывать динамическое добавление состояний

const initialState = {
    img-1: {
        x: 0,
        y: 0,
        rotation: 0
    }
}

const reducer= (state, action) =>{
   switch(action.type) {
        'ADD_IMAGE': return  {
             ...state,
             [action.itemkey]: action.payload
         }
         'UPDATE_IMAGE: return {
             ...state,
             [action.id]: {...state[action.id], ...action.payload}
         }
         default: {
            return state;
         }
   }
}

В функциональном компоненте

const [state, dispatch] = useReducer(reducer, initialState);


const createImg = (newImg) => { dispatch({ type: 'ADD_IMAGE', payload: {newImg}, itemKey: `item-${Object.keys(state).length + 1}`

const updateImg = (id, updatedImg) => {
   dispatch({type: 'UPDATE_IMAGE', id, payload: updatedImg })
)}
...