如何使用React钩子动态创建处于状态的对象?

时间:2019-02-20 10:19:18

标签: javascript reactjs react-hooks

直到现在,在我的代码中,我有一个对象可以代表页面上图像的所有数据

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 :(得分:3)

代替使用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 })
)}