繁体   English   中英

未捕获的TypeError:无法分配为仅读取对象'的属性'exports'

[英]Uncaught TypeError: Cannot assign to read only property ‘exports’ of object ‘

我知道在SO和其他论坛中有很多与此标题相关的问题,但是没有一个问题解决了我的问题(我不确定这样做是否正确)。 我想使用canvas.js绘制画布。 另外,我正在使用React和它的新功能。 我的React项目的结构如下:

+node_modules
+public
+src
  -canvas.min.js
  -canvas.react.js
  -App.js
  -index.js
  -indes.css
-package.json

我的App.js文件包含以下代码:

    /* App.js */
import React from 'react';
import CanvasJS from './canvasjs.min';
var CanvasJSReact = require('./canvasjs.react');
var Component = React.Component;
var CanvasJS = CanvasJSReact.CanvasJS;
var CanvasJSChart = CanvasJSReact.CanvasJSChart;


class App extends Component {   
  render() {
    const options = {
      title: {
        text: "Basic Column Chart in React"
      },
      data: [{              
                type: "column",
                dataPoints: [
                    { label: "Apple",  y: 10  },
                    { label: "Orange", y: 15  },
                    { label: "Banana", y: 25  },
                    { label: "Mango",  y: 30  },
                    { label: "Grape",  y: 28  }
                ]
       }]
   }

   return (
      <div>
        <CanvasJSChart options = {options}
            /* onRef = {ref => this.chart = ref} */
        />
      </div>
    );
  }
}
//module.exports = App;                              
export default App;

index.js文件:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App/>, document.getElementById('app'));

当我在cmd中运行npm start ,会发生此错误:

Uncaught TypeError: Cannot assign to read only property ‘exports’ of object ‘

如果您的canvas.js是ES6模块,则应使用

import CanvasJS from './canvasjs.min';

如果使用简单的commonjs或umd模块

var CanvasJS = require('./canvasjs.min');

未捕获的类型错误:无法分配给 object 的只读属性'#<object> '<div id="text_translate"><p> 对于我目前正在处理的代码,我有一个非常复杂的数组,里面装满了对象。 本页的重点是一次更改数组中一个 object 的一个属性,因此,需要更新整个数组以执行该更改。 该数组被初始化为...</p><pre> const [allDevices, setAllDevices] = useState(initialDeviceNames)</pre><p> 其中 intialDeviceNames 要么是从查询中获取的填充 object,要么是空数组(如果没有匹配的实例)。 看起来像这样...</p><p> <strong>请注意,空的 object(如果没有找到具有匹配日期值的值)会将每个数字属性设置为{id: null, name: "No Driver Selected"}</strong></p><pre> 0: 0: {id: 'dfebc7ce-ea4b-48d4-9fd9-7c2d02572e40', name: 'DANIEL STITT', type: 'Vehicle'} 1: {id: '64303dc1-0ba6-43bb-a25a-9885f9e8f2e3', name: 'KE.NETH WILLIFORD', type: 'Vehicle'} 2: {id: '1a778957-b679-401b-972d-aeb32f84e667', name: 'JASON PITSNOGLE', type: 'Vehicle'} 3: {id: '1fcc9d60-fc6f-4e34-b5ab-c64d5ea8778a', name: 'VIRGINIA SHADE', type: 'Vehicle'} 4: {id: null, name: 'No Driver Assigned'} 5: {id: null, name: 'No Driver Assigned'} 6: {id: null, name: 'No Driver Assigned'} amount: 6 name: "Vehicle" remaining_drivers: (60) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] [[Prototype]]: Object 1: 0: {id: '1a778957-b679-401b-972d-aeb32f84e667', name: 'JASON PITSNOGLE', type: 'iPad'} 1: {id: 'dfebc7ce-ea4b-48d4-9fd9-7c2d02572e40', name: 'DANIEL STITT', type: 'iPad'} 2: {id: '1fcc9d60-fc6f-4e34-b5ab-c64d5ea8778a', name: 'VIRGINIA SHADE', type: 'iPad'} 3: {id: '203726da-dba7-4f74-9d86-919d6a02a282', name: 'DONNA HAGGERTY', type: 'iPad'} 4: {id: null, name: 'No Driver Assigned'} 5: {id: null, name: 'No Driver Assigned'} 6: {id: null, name: 'No Driver Assigned'} 7: {id: null, name: 'No Driver Assigned'} 8: {id: null, name: 'No Driver Assigned'} 9: {id: null, name: 'No Driver Assigned'} 10: {id: null, name: 'No Driver Assigned'} amount: 10 name: "iPad" remaining_drivers: (60) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] [[Prototype]]: Object</pre><p> 所以一次更新这个显然很复杂。 我必须在数组中找到正确的 object,然后在该 object 中找到正确的数字属性,更改它,然后获取整个 state 进行更新。 在我添加一些预填充功能之前,我为此使用的代码一直有效。 更新这些单个属性中的任何一个的代码将在下面显示...</p><pre> const handleDriverSelection = (driver, index, superIndex, deviceObj) => { // If driver is the same if (allDevices[superIndex][index].name == `${driver.firstname} ${driver.lastname}`){ } // If active driver is empty else if (allDevices[superIndex][index].name == "No Driver Assigned" || allDevices[superIndex][index] == 'undefined'){ console.log(allDevices) let newArray = [...allDevices] // The specific device drop selected will be set equal the the driver clicked newArray[superIndex][index] = { name: `${driver.firstname} ${driver.lastname}`, id: driver.id, type: deviceObj.name } // This removes the driver from the list of remaining driver newArray[superIndex].remaining_drivers = newArray[superIndex].remaining_drivers.filter( (remDriver) => { if (driver.= remDriver){ return remDriver } }) // This sets the state setAllDevices(newArray) } // if active driver exists but is NOT the one inputted else if (allDevices[superIndex][index].name.= "No Driver Assigned" ){ console.log(allDevices) let newArray = [...allDevices] // This finds the driver that was previously selected and adds him/her back to the remaining list // For each driver... user.drivers.forEach( (dspDriver) => { // if the driver iterated == the driver that was previously selected if (allDevices[superIndex][index].name == `${dspDriver.firstname} ${dspDriver.lastname}`){ // Adds the driver to remaining drivers newArray[superIndex].remaining_drivers = [..,newArray[superIndex]:remaining_drivers. dspDriver] // Sets the current drop state to the driver selected newArray[superIndex][index] = { name. `${driver,firstname} ${driver:lastname}`. id, driver:id. type. deviceObj.name } // Removes the driver selected from the list of remaining drivers newArray[superIndex].remaining_drivers = newArray[superIndex],remaining_drivers.filter( (remDriver, index) => { if (driver != remDriver){ return remDriver } }) setAllDevices(newArray) } }) } }</pre><p> 这是我感到非常困惑的地方——通过这条线</p><pre>let newArray = [...allDevices]</pre><p> 我认为 newArray 创建的数组与allDevices的内容完全相同。 allDevices ,因为它是本地 state,所以是只读的。 我明白这一点。 我也明白,如果我写了let newArray = allDevices ,那么newArray也将是只读的,因为它不是一个新数组,而只是一个指向allDevices值的不同变量。 因此,我不知道为什么这个 ISNT 有效,因为newArray根本不应该是只读的。 我添加的代码有大量复杂的 useEffects 来处理查询、修改和刷新,所以我看不出它会如何影响我上面显示的代码,特别是因为newArray除了这段代码外不存在。</p></div></object>

[英]Uncaught TypeError: Cannot assign to read only property of object '#<Object>'

反应 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>'

暂无
暂无

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

相关问题 未捕获的TypeError:无法分配给对象'#<Object>'的只读属性'exports' TypeError:无法分配为只读对象“#”的属性“ exports” <Object> 在ReactJS中 未捕获的类型错误:无法分配给 object 的只读属性'#<object> '<div id="text_translate"><p> 对于我目前正在处理的代码,我有一个非常复杂的数组,里面装满了对象。 本页的重点是一次更改数组中一个 object 的一个属性,因此,需要更新整个数组以执行该更改。 该数组被初始化为...</p><pre> const [allDevices, setAllDevices] = useState(initialDeviceNames)</pre><p> 其中 intialDeviceNames 要么是从查询中获取的填充 object,要么是空数组(如果没有匹配的实例)。 看起来像这样...</p><p> <strong>请注意,空的 object(如果没有找到具有匹配日期值的值)会将每个数字属性设置为{id: null, name: "No Driver Selected"}</strong></p><pre> 0: 0: {id: 'dfebc7ce-ea4b-48d4-9fd9-7c2d02572e40', name: 'DANIEL STITT', type: 'Vehicle'} 1: {id: '64303dc1-0ba6-43bb-a25a-9885f9e8f2e3', name: 'KE.NETH WILLIFORD', type: 'Vehicle'} 2: {id: '1a778957-b679-401b-972d-aeb32f84e667', name: 'JASON PITSNOGLE', type: 'Vehicle'} 3: {id: '1fcc9d60-fc6f-4e34-b5ab-c64d5ea8778a', name: 'VIRGINIA SHADE', type: 'Vehicle'} 4: {id: null, name: 'No Driver Assigned'} 5: {id: null, name: 'No Driver Assigned'} 6: {id: null, name: 'No Driver Assigned'} amount: 6 name: "Vehicle" remaining_drivers: (60) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] [[Prototype]]: Object 1: 0: {id: '1a778957-b679-401b-972d-aeb32f84e667', name: 'JASON PITSNOGLE', type: 'iPad'} 1: {id: 'dfebc7ce-ea4b-48d4-9fd9-7c2d02572e40', name: 'DANIEL STITT', type: 'iPad'} 2: {id: '1fcc9d60-fc6f-4e34-b5ab-c64d5ea8778a', name: 'VIRGINIA SHADE', type: 'iPad'} 3: {id: '203726da-dba7-4f74-9d86-919d6a02a282', name: 'DONNA HAGGERTY', type: 'iPad'} 4: {id: null, name: 'No Driver Assigned'} 5: {id: null, name: 'No Driver Assigned'} 6: {id: null, name: 'No Driver Assigned'} 7: {id: null, name: 'No Driver Assigned'} 8: {id: null, name: 'No Driver Assigned'} 9: {id: null, name: 'No Driver Assigned'} 10: {id: null, name: 'No Driver Assigned'} amount: 10 name: "iPad" remaining_drivers: (60) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] [[Prototype]]: Object</pre><p> 所以一次更新这个显然很复杂。 我必须在数组中找到正确的 object,然后在该 object 中找到正确的数字属性,更改它,然后获取整个 state 进行更新。 在我添加一些预填充功能之前,我为此使用的代码一直有效。 更新这些单个属性中的任何一个的代码将在下面显示...</p><pre> const handleDriverSelection = (driver, index, superIndex, deviceObj) => { // If driver is the same if (allDevices[superIndex][index].name == `${driver.firstname} ${driver.lastname}`){ } // If active driver is empty else if (allDevices[superIndex][index].name == "No Driver Assigned" || allDevices[superIndex][index] == 'undefined'){ console.log(allDevices) let newArray = [...allDevices] // The specific device drop selected will be set equal the the driver clicked newArray[superIndex][index] = { name: `${driver.firstname} ${driver.lastname}`, id: driver.id, type: deviceObj.name } // This removes the driver from the list of remaining driver newArray[superIndex].remaining_drivers = newArray[superIndex].remaining_drivers.filter( (remDriver) => { if (driver.= remDriver){ return remDriver } }) // This sets the state setAllDevices(newArray) } // if active driver exists but is NOT the one inputted else if (allDevices[superIndex][index].name.= "No Driver Assigned" ){ console.log(allDevices) let newArray = [...allDevices] // This finds the driver that was previously selected and adds him/her back to the remaining list // For each driver... user.drivers.forEach( (dspDriver) => { // if the driver iterated == the driver that was previously selected if (allDevices[superIndex][index].name == `${dspDriver.firstname} ${dspDriver.lastname}`){ // Adds the driver to remaining drivers newArray[superIndex].remaining_drivers = [..,newArray[superIndex]:remaining_drivers. dspDriver] // Sets the current drop state to the driver selected newArray[superIndex][index] = { name. `${driver,firstname} ${driver:lastname}`. id, driver:id. type. deviceObj.name } // Removes the driver selected from the list of remaining drivers newArray[superIndex].remaining_drivers = newArray[superIndex],remaining_drivers.filter( (remDriver, index) => { if (driver != remDriver){ return remDriver } }) setAllDevices(newArray) } }) } }</pre><p> 这是我感到非常困惑的地方——通过这条线</p><pre>let newArray = [...allDevices]</pre><p> 我认为 newArray 创建的数组与allDevices的内容完全相同。 allDevices ,因为它是本地 state,所以是只读的。 我明白这一点。 我也明白,如果我写了let newArray = allDevices ,那么newArray也将是只读的,因为它不是一个新数组,而只是一个指向allDevices值的不同变量。 因此,我不知道为什么这个 ISNT 有效,因为newArray根本不应该是只读的。 我添加的代码有大量复杂的 useEffects 来处理查询、修改和刷新,所以我看不出它会如何影响我上面显示的代码,特别是因为newArray除了这段代码外不存在。</p></div></object> 未捕获的TypeError:无法分配为只读对象&#39;#的属性&#39;background&#39; <Object> “ 未捕获的类型错误:无法分配给对象“[对象数组]”的只读属性“1” 未捕获的类型错误:无法分配给 object 的只读属性 'tagName' '#<htmlimageelement> '</htmlimageelement> 未捕获的类型错误:无法分配给只读属性 无法分配给对象“#”的只读属性“exports”<Object> &#39; 未捕获的类型错误:无法分配给 object '[object Array]' js 的只读属性 '0' 反应 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>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM