![](/img/trans.png)
[英]Uncaught TypeError: Cannot assign to read only property 'background' of object '#<Object>'
[英]React redux, Uncaught TypeError: Cannot assign to read only property 'current' of object '#<Object>'
我正在制作一个网站来修改数据库数据。 一、组件的结构如下
<Contents />
<Table />
<Row />
<Column />
<Input />
创建行组件时,创建输入组件的引用并由 redux 管理它。
const StyledRow = styled.div`
text-align:center;
display:flex;
align-items:center;
`;
const DeleteButton = styled(Button)`
background-color: #ff7787;
margin-right:5px;
color:white;
width:40px;
${({top}) => top && css`
background-color:white;
color:white;
width:40px;
`}
`;
function Row({top, rowId}){
const dispatch = useDispatch();
const columns = useMemo(() => columnPhoneInfo,[]);
const inputsRef = useMemo(()=>
!top &&
Array(8).fill(0).map(() => createRef()
),[]);
// const inputsRef = useRef([]);
useEffect(()=> {
// console.log(rowId,top);
!top &&
dispatch(phoneDataAddRef(rowId,inputsRef));
},[]);
const handleDeleteButton = useCallback( (id) => {
dispatch(phoneDataUpdate.Delete(id));
},[]);
if( top ) return(
<StyledRow>
<DeleteButton top/>
{columns.map((column)=>
<Column key={`head_${column.name}`} width={column.width} top>
{column.name}
</Column>
)}
</StyledRow>
);
return(
<StyledRow>
<DeleteButton onClick={()=>handleDeleteButton(rowId)}> delete </DeleteButton>
{columns.map((column, index)=>
<Column key={`row_${rowId}_${column.name}`} width={column.width} textalign={column.textalign}>
<Input ref={inputsRef[index] } colIndex={index} id={rowId} column={column} />
{/* <Input colIndex={index} id={rowId} column={column} /> */}
</Column>
)}
</StyledRow>
);
}
export default React.memo(Row);
输入组件只接收 ref 作为 forwardRef
const StyledInput = styled.input`
${({ width, textalign })=>css`
width:${width};
text-align:${textalign};
`}
`;
const Input = forwardRef(({colIndex, id},inputRef) =>{
const dispatch = useDispatch();
const didShowAlert = useRef(false);
const nowColumnInfo = columnPhoneInfo[colIndex];
const nowColumnValidCheck = inputValidCheck[colIndex];
const { nowVal, firstVal, isAddedRow } = useSelector(state =>({
nowVal : state.phoneData.data.rows.find(val=>val.id === id)[nowColumnInfo.colname],
firstVal : state.phoneData.firstData.lastId < id
? null
: state.phoneData.firstData.rows.find(val=>val.id===id)[nowColumnInfo.colname],
isAddedRow : state.phoneData.firstData.lastId < id
? true
: false,
}),shallowEqual);
const callbackDispatch = useCallback((dispatchFunc) =>{
return(...args)=>{
dispatch(dispatchFunc(...args));
}
},[dispatch]);
//////////////////////
const inputChange = useCallback( (value) =>
dispatch(phoneDataUpdate.Change(id,nowColumnInfo.colname, value))
,[nowColumnInfo.colname, dispatch, id]);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const updateListChange = callbackDispatch(phoneDataUpdateList.Change);
const updateListDelete = callbackDispatch(phoneDataUpdateList.Delete);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const handleChange = useCallback( (e) => {
// ... todo handle change
},[]);
/////////////////////////////////////////////////////////
const handleBlur = useCallback( (e) =>{
// ... todo handle blur
},[]);
return(
<StyledInput
textalign={nowColumnInfo.textalign}
width={nowColumnInfo.width}
value={nowVal === null ? '': nowVal }
onChange={handleChange}
onBlur={handleBlur}
ref={inputRef}
// placeholder={}
/>
);
});
export default React.memo(Input);
最后,redux 模块
////////////////////////////////////////////////////////
const PHONE_DATA_DELETE = 'phoneData/PHONE_DATA_DELETE';
////////////////////////////////////////////////////////
const PHONE_DATA_ADD_REF = 'phoneData/PHONE_DATA_ADD_REF';
////////////////////////////////////////////////////////
const dataInitRow = {
id:null,
model_name:null,
machine_name:null,
shipping_price:null,
maker:null,
created:null,
battery:null,
screen_size:null,
storage:null,
};
const dataInit = {
lastId:null,
rows:[],
}
const initialState = {
state:{
loading:false,
error:false,
},
data:dataInit,
refData:[],
firstData:dataInit,
dataChangeList:{
dataAddList:[],
dataDeleteList:[],
dataUpdateList:[],
},
};
const phoneDataFetchAsync = createPromiseThunk(PHONE_DATA, restAPI.getAllPhoneInfo);
////////////////////////////////////////////////////////
const phoneDataAddRef=(id, ref) =>({
type:PHONE_DATA_ADD_REF,
id:id,
ref:ref,
});
const phoneDataUpdateList = ({
Change:(id,colName, value) => ({
type:PHONE_DATA_UPDATE_LIST_CHANGE,
id: id,
colName: colName,
value: value,
}),
Delete:(id, colName) => ({
type:PHONE_DATA_UPDATE_LIST_DELETE,
id: id,
}),
});
////////////////////////////////////////////////////////
export default function phoneData(state = initialState, action){
// console.log(`add: ${state.dataChangeList.dataAddList}, delete: ${state.dataChangeList.dataDeleteList}, change: ${state.dataChangeList.dataUpdateList}`);
switch(action.type)
case PHONE_DATA_DELETE:
return produce(state, draft=>{
console.log(action);
const idx = state.dataChangeList.dataAddList.findIndex( val => val === action.id);
if( idx === -1 )
draft.dataChangeList.dataDeleteList.push(action.id);
else
draft.dataChangeList.dataAddList.splice(idx,1);
draft.refData = state.refData.filter(row => row.id !== action.id);
draft.data.rows = state.data.rows.filter(row =>row.id !== action.id);
});
////////////////////////////////////////////////////////////////////////////////////////////////////////////
case PHONE_DATA_ADD_REF:
return produce(state, draft=>{
draft.refData.push({id:action.id, refs:action.ref});
});
////////////////////////////////////////////////////////////////////////////////////////////////////////////
default:
return state;
}
}
export {phoneDataFetchAsync,
phoneDataDelete,,
phoneDataAddRef,
};
问题区域是删除按钮。 当我按下按钮时,就会出现该错误。 但是如果不向 state 添加 ref,则不会发生错误。 或者即使我注释掉底部,也没有错误。
draft.data.rows = state.data.rows.filter(row =>row.id !== action.id);
或者注释掉底部
draft.refData.push({id:action.id, refs:action.ref});
我今天整天都在尝试修复它,但我不知道出了什么问题。 我该如何解决?
您在此处尝试执行的操作违反了 Redux 的“基本”规则中的一项而不是两项。
Ref 对象在设计上是可变的。 通过更新 ref object 的.current
属性来更改引用,但 object 实例保持不变。 This violates Redux rules that state must be immutable because the Redux state can be mutated by unrelated React code.
Redux 存储中的所有数据都应该能够转换为 JSON string
并返回。 在该转换中丢失的任何内容都不属于 Redux。 DOM 元素的实例是不可序列化的。
您需要弄清楚需要哪些原始数据来表示您的 state。 将该数据存储在 Redux 中,并使用它来生成正确的 DOM 元素。 将 DOM 存储在 Redux 中是倒退的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.