首页 > 解决方案 > 如何使用反应钩子动态创建状态对象?

问题描述

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

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

有没有更清洁/更易读的方法,还是我只需要求助于将所有内容嵌套在一个对象中?

标签: javascriptreactjsreact-hooks

解决方案


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

推荐阅读