How to dynamically create objects in state with react hooks?

问题: until now in my code, I had an object that would represent all the data for an image on the page this.state = { img-1: { x: 0, y: 0, rotation:...

问题:

until now in my code, I had an object that would represent all the data for an image on the page

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

every time the object receives a new child it adds a new img-id to state that is updated everytime <img id=${id} update={this.update} /> is updated.

Moving functionality like calculating the coordinates or the rotation into their own custom hooks would greatly improve my code in terms of maintainability and testing but I don't really see a good way to store all of this data in a centralized object with hooks.

As far as I understand it I'd have to set either a new

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

for every child which, as I understand it, isn't possible as hooks have to be declared at the top level or to set a very deep object that would be kind of clunky to update:

[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} }
)}

Is there a cleaner / more readable approach or do I just have to resort to nesting everything in one object?


回答1:

Instead of using a useState, you can make use of useReducer and control your states better and handle dynamic addition of states

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;
         }
   }
}

In functional component

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 })
)}
  • 发表于 2019-02-21 13:08
  • 阅读 ( 160 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除