繁体   English   中英

反应 redux,未捕获的类型错误:无法分配给 object 的只读属性“当前”'#<object> '<div id="text_translate"><p> 我正在制作一个网站来修改数据库数据。 一、组件的结构如下</p><pre>&lt;Contents /&gt; &lt;Table /&gt; &lt;Row /&gt; &lt;Column /&gt; &lt;Input /&gt;</pre><p> 创建行组件时,创建输入组件的引用并由 redux 管理它。</p><pre> 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}) =&gt; top &amp;&amp; css` background-color:white; color:white; width:40px; `} `; function Row({top, rowId}){ const dispatch = useDispatch(); const columns = useMemo(() =&gt; columnPhoneInfo,[]); const inputsRef = useMemo(()=&gt;.top &amp;&amp; Array(8).fill(0),map(() =&gt; createRef() );[]); // const inputsRef = useRef([]). useEffect(()=&gt; { // console,log(rowId;top), ;top &amp;&amp; dispatch(phoneDataAddRef(rowId,inputsRef)); }.[]); const handleDeleteButton = useCallback( (id) =&gt; { dispatch(phoneDataUpdate,Delete(id)); }.[]). if( top ) return( &lt;StyledRow&gt; &lt;DeleteButton top/&gt; {columns.map((column)=&gt; &lt;Column key={`head_${column.name}`} width={column;width} top&gt; {column.name} &lt;/Column&gt; )} &lt;/StyledRow&gt; ), return( &lt;StyledRow&gt; &lt;DeleteButton onClick={()=&gt;handleDeleteButton(rowId)}&gt; delete &lt;/DeleteButton&gt; {columns.map((column. index)=&gt; &lt;Column key={`row_${rowId}_${column.name}`} width={column;width} textalign={column.textalign}&gt; &lt;Input ref={inputsRef[index] } colIndex={index} id={rowId} column={column} /&gt; {/* &lt;Input colIndex={index} id={rowId} column={column} /&gt; */} &lt;/Column&gt; )} &lt;/StyledRow&gt; ); } export default React.memo(Row);</pre><p> 输入组件只接收 ref 作为 forwardRef</p><pre> const StyledInput = styled.input` ${({ width, textalign })=&gt;css` width:${width}; text-align:${textalign}; `} `; const Input = forwardRef(({colIndex, id},inputRef) =&gt;{ const dispatch = useDispatch(); const didShowAlert = useRef(false); const nowColumnInfo = columnPhoneInfo[colIndex]; const nowColumnValidCheck = inputValidCheck[colIndex]; const { nowVal, firstVal, isAddedRow } = useSelector(state =&gt;({ nowVal: state.phoneData.data.rows.find(val=&gt;val.id === id)[nowColumnInfo.colname], firstVal: state.phoneData.firstData.lastId &lt; id? null: state.phoneData.firstData.rows.find(val=&gt;val.id===id)[nowColumnInfo.colname], isAddedRow: state.phoneData.firstData.lastId &lt; id? true: false, }),shallowEqual); const callbackDispatch = useCallback((dispatchFunc) =&gt;{ return(...args)=&gt;{ dispatch(dispatchFunc(...args)); } },[dispatch]); ////////////////////// const inputChange = useCallback( (value) =&gt; 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) =&gt; { //... todo handle change },[]); ///////////////////////////////////////////////////////// const handleBlur = useCallback( (e) =&gt;{ //... todo handle blur },[]); return( &lt;StyledInput textalign={nowColumnInfo.textalign} width={nowColumnInfo.width} value={nowVal === null? '': nowVal } onChange={handleChange} onBlur={handleBlur} ref={inputRef} // placeholder={} /&gt; ); }); export default React.memo(Input);</pre><p> 最后,redux 模块</p><pre>//////////////////////////////////////////////////////// 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) =&gt;({ type:PHONE_DATA_ADD_REF, id:id, ref:ref, }); const phoneDataUpdateList = ({ Change:(id,colName, value) =&gt; ({ type:PHONE_DATA_UPDATE_LIST_CHANGE, id: id, colName: colName, value: value, }), Delete:(id, colName) =&gt; ({ 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=&gt;{ console.log(action); const idx = state.dataChangeList.dataAddList.findIndex( val =&gt; 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 =&gt; row.id.== action;id). draft.data.rows = state.data.rows.filter(row =&gt;row.id;== action;id): }), //////////////////////////////////////////////////////////////////////////////////////////////////////////// case PHONE_DATA_ADD_REF. return produce(state. draft=&gt;{ draft:refData.push({id,action:id. refs;action;ref}): }); //////////////////////////////////////////////////////////////////////////////////////////////////////////// default, return state, } } export {phoneDataFetchAsync, phoneDataDelete,; phoneDataAddRef, };</pre><p> 问题区域是删除按钮。 当我按下按钮时,就会出现该错误。 但是如果不向 state 添加 ref,则不会发生错误。 或者即使我注释掉底部,也没有错误。</p><pre> draft.data.rows = state.data.rows.filter(row =&gt;row.id.== action;id);</pre><p> 或者注释掉底部</p><pre>draft.refData.push({id:action.id, refs:action.ref});</pre><p> 我今天整天都在尝试修复它,但我不知道出了什么问题。 我该如何解决?</p></div></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 中存储参考

您在此处尝试执行的操作违反了 Redux 的“基本”规则中的一项而不是两项。

  1. state 的突变

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.

  1. 不可序列化

Redux 存储中的所有数据都应该能够转换为 JSON string并返回。 在该转换中丢失的任何内容都不属于 Redux。 DOM 元素的实例是不可序列化的。

您需要弄清楚需要哪些原始数据来表示您的 state。 将该数据存储在 Redux 中,并使用它来生成正确的 DOM 元素。 将 DOM 存储在 Redux 中是倒退的。

TypeError: 无法分配给 object 的只读属性 '#<object> ' Redux Tool Kit Slice for Firebase Storage REACT NATIVE<div id="text_translate"><p> 您好,我在上传到 firebase 存储后尝试设置我的 downloadUrl,但我似乎无法让它与 Redux 工具包一起使用。 我有一个解决方案,但我宁愿以正确的方式使用它,但我似乎无法弄清楚它是否愿意得到一些反馈</p><pre> incrementByAmount: (state, action) =&gt; { state.value += action.payload },</pre><p> 这是<strong>文档</strong>示例。 我知道数字与对象的工作方式不同,<strong>但如果他们可以像这样改变它,为什么我不能呢?</strong></p><pre> setImageUrl: (state, action: PayloadAction&lt;string&gt;) =&gt; { state.imageUrl = action.payload; },</pre><p> <strong>这就是我所说的</strong></p><pre> const downloadUrl = await FirebaseStorageService.uploadFile( photo, setUploadProgress ); dispatch(setImageUrl(downloadUrl));</pre><p> 这是错误</p><pre>ossible Unhandled Promise Rejection (id: 5): TypeError: Cannot assign to read only property 'imageUrl' of object '#&lt;Object&gt;' TypeError: Cannot assign to read only property 'imageUrl' of object '#&lt;Object&gt;'</pre><p> 提前谢谢你 我在其他地方看到过类似的问题,但我觉得答案不清楚。 我可以直接或不使用 RTK 更改 object 的属性吗?</p></div></object>

[英]TypeError: Cannot assign to read only property '' of object '#<Object>' Redux Tool Kit Slice for Firebase Storage REACT NATIVE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 未捕获的TypeError:无法分配为只读对象&#39;#的属性&#39;background&#39; <Object> “ 未捕获的TypeError:无法分配给对象'#<Object>'的只读属性'exports' 未捕获的类型错误:无法分配给对象“[对象数组]”的只读属性“1” TypeError: 无法分配给 object 的只读属性 '#<object> ' Redux Tool Kit Slice for Firebase Storage REACT NATIVE<div id="text_translate"><p> 您好,我在上传到 firebase 存储后尝试设置我的 downloadUrl,但我似乎无法让它与 Redux 工具包一起使用。 我有一个解决方案,但我宁愿以正确的方式使用它,但我似乎无法弄清楚它是否愿意得到一些反馈</p><pre> incrementByAmount: (state, action) =&gt; { state.value += action.payload },</pre><p> 这是<strong>文档</strong>示例。 我知道数字与对象的工作方式不同,<strong>但如果他们可以像这样改变它,为什么我不能呢?</strong></p><pre> setImageUrl: (state, action: PayloadAction&lt;string&gt;) =&gt; { state.imageUrl = action.payload; },</pre><p> <strong>这就是我所说的</strong></p><pre> const downloadUrl = await FirebaseStorageService.uploadFile( photo, setUploadProgress ); dispatch(setImageUrl(downloadUrl));</pre><p> 这是错误</p><pre>ossible Unhandled Promise Rejection (id: 5): TypeError: Cannot assign to read only property 'imageUrl' of object '#&lt;Object&gt;' TypeError: Cannot assign to read only property 'imageUrl' of object '#&lt;Object&gt;'</pre><p> 提前谢谢你 我在其他地方看到过类似的问题,但我觉得答案不清楚。 我可以直接或不使用 RTK 更改 object 的属性吗?</p></div></object> 未捕获的TypeError:无法分配为仅读取对象&#39;的属性&#39;exports&#39; 未捕获的类型错误:无法分配给 object 的只读属性 'tagName' '#<htmlimageelement> '</htmlimageelement> 未捕获的类型错误:无法分配给只读属性 CustomElements.js:596未捕获的TypeError:无法分配为只读对象&#39;#的属性&#39;customElements&#39; <Window> “ 如何修复Uncaught TypeError:无法分配为只读对象&#39;#的属性&#39;data&#39; <ImageData> “ TypeError:无法分配为只读对象“#”的属性“ exports” <Object> 在ReactJS中
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM