Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 正在尝试使用来自子组件2的数据更新子组件1,而不重新加载子组件2_Javascript_Reactjs_React Hooks_Render - Fatal编程技术网

Javascript 正在尝试使用来自子组件2的数据更新子组件1,而不重新加载子组件2

Javascript 正在尝试使用来自子组件2的数据更新子组件1,而不重新加载子组件2,javascript,reactjs,react-hooks,render,Javascript,Reactjs,React Hooks,Render,我正在从一个循环生成一个重JSX数组。 它创建了很多表格。 我想用选定行上的数据更新徽章。但它让我所有的桌子都重新上座了。更新一个徽章需要很长时间。 我试图使用useMemo()来防止在数据未更改的情况下创建表,但来自父级的回调函数不更新状态 我正在尝试做的代码示例=> function App() { const [tableData, setTableData] = useState(null) const [badgeData, setBadgeData] = useSta

我正在从一个循环生成一个重JSX数组。 它创建了很多表格。 我想用选定行上的数据更新徽章。但它让我所有的桌子都重新上座了。更新一个徽章需要很长时间。 我试图使用
useMemo()
来防止在数据未更改的情况下创建表,但来自父级的回调函数不更新状态

我正在尝试做的代码示例=>

function App() {
    const [tableData, setTableData] = useState(null)
    const [badgeData, setBadgeData] = useState(null)
    const jsx = useMemo(() => createTable(tableData), [tableData])

    function updateBadge(selectedRows) {
        setBadgeData(addNewRow(selectedRows))
    }


    function createTable(data) {
        let jsx = []
        data.forEach((item) => {
            jsx.push(<TableComponent data={data.var} onRowSelect={updateBadge}/>)
        })
        return jsx;
    }

    return (
        <div>
            <HandleDataGeneration setData={setTableData}/>
            <MyBadgeComponent data={badgeData}/>
            {jsx}
        </div>
    );
}
函数应用程序(){
常量[tableData,setTableData]=useState(null)
常量[badgeData,setBadgeData]=useState(null)
const jsx=useMoom(()=>createTable(tableData),[tableData])
函数UpdateEdge(selectedRows){
setBadgeData(addNewRow(selectedRows))
}
函数createTable(数据){
让jsx=[]
data.forEach((项目)=>{
jsx.push()
})
返回jsx;
}
返回(
{jsx}
);
}
在这种情况下,只有对UpdateEdge函数的第一次调用会重新提交父函数,但不会重新提交nexts调用(我想这是因为我没有发送新的道具,并且函数被复制并且没有链接)

也许我的架构不好,或者可能有一些解决方案可以在不重新提交所有表的情况下更新这个组件。谢谢你的帮助

编辑:

表组件

const TableCompoennt = React.memo((props) => { // after edit but it was a classic fn
    const classes = useStyles();
    const [expanded, setExpanded] = useState(props.data ? `panel${props.i}` : false);
    let disabled = false;

    const handleChange = (panel) => (event, isExpanded) => {
        setExpanded(isExpanded ? panel : false);
    };
    if (isNaN(props.data.var)) {
        props.data.var = x
    }
    if (!props.data)
        disabled = true;
    return (
        <ExpansionPanel TransitionProps={{ unmountOnExit: false }} expanded={expanded === `panel${props.i}`} onChange={handleChange(`panel${props.i}`)} disabled={disabled}>
            <ExpansionPanelSummary
                expandIcon={<ExpandMoreIcon/>}
                aria-controls="panel1bh-content"
                id="panel1bh-header"
            >
                <Tooltip title={props.data.var}>
                <Typography className={classes.heading}>{props.data.var}-{props.data.var}</Typography>
                </Tooltip>
                {!disabled ?
                    <Typography
                        className={classes.secondaryHeading}>{expanded ? "click to hide data" : "click to display data"}</Typography> :
                    <Typography
                        className={classes.secondaryHeading}>no data</Typography>
                }
            </ExpansionPanelSummary>
            <ExpansionPanelDetails>
                <MyTable data={props.data} var={props.var}
                         key={props.i} id={props.i}  style={{width: "100%"}} updateBadge={props.updateBadge}/>
            </ExpansionPanelDetails>
        </ExpansionPanel>
    )
})
const TableComponent = React.memo((props) => {
 // Rest of the TableComponent code
})
consttablecomponent=React.memo((道具)=>{//编辑后,但这是一个经典的fn
const classes=useStyles();
const[expanded,setExpanded]=useState(props.data?`panel${props.i}`:false);
设禁用=假;
常量句柄更改=(面板)=>(事件,isExpanded)=>{
setExpanded(isExpanded?面板:假);
};
if(isNaN(props.data.var)){
props.data.var=x
}
如果(!props.data)
禁用=真;
返回(
{props.data.var}-{props.data.var}
{!残疾?
{展开?“单击以隐藏数据”:“单击以显示数据”}:
没有数据
}
)
})
我的桌子

export default React.memo((props) => { // same here
    const [open, setOpen] = useState(false);
    const [rowData, setRowData] = useState(null);
    const [rows, setRows] = useState(props.myRates);

    calcTotal(rows);
    useEffect(() => {
        setRows(props.myRates)
    }, [props]);

    return (
        <div style={{width: "100%"}}>
            {(rows && rows.length) &&
                <div style={{width: "100%"}}>
                    <Modal open={open} rowData={rowData} setRowData={setRowData}
                                setOpen={(value) => setOpen(value)}/>
                    <Paper style={{height: 400, width: '100%'}}>
                    <SimpleTable
                        columns={columns}
                        rows={rows}
                        handleRowClick={(row) =>{
                                setOpen(true);
                                setRowData(row);
                        }}
                        handleSelect={(row) => {
                            if (!row.selected)
                                row.selected = false;
                            row.selected = !row.selected;
                            props.updateBadge(row)
                    }}
                    />
                    </Paper>
                </div>}
        </div>
    );
})
export default React.memo((props)=>{//此处相同
const[open,setOpen]=useState(false);
const[rowData,setRowData]=useState(null);
const[rows,setRows]=useState(props.myRates);
calcTotal(行);
useffect(()=>{
设置行(props.myRates)
}[道具];
返回(
{(行和行长度)&&
setOpen(值)}/>
{
setOpen(真);
setRowData(行);
}}
handleSelect={(行)=>{
如果(!row.selected)
row.selected=false;
row.selected=!row.selected;
props.UpdateEdge(行)
}}
/>
}
);
})
简单的

const SimpleTable = React.memo((props) =>  {
    const classes = useStyles();
    let dataLabel = generateLabel(props.columns);

    function getRowData(row) {
        props.handleRowClick(row);
    }

    return (
        <TableContainer component={Paper}>
            <Table className={classes.table} aria-label="simple table">
                <TableHead>
                    <TableRow>
                        {dataLabel}
                    </TableRow>
                </TableHead>
                <TableBody>
                    {props.rows.map((row) => (
                        <TableRow key={row.unique_code} selected={row.selected} hover onClick={() => {getRowData(row)}}>
                            {generateRow(props.columns, row)}
                            <TableCell onClick={(event) => {
                                event.stopPropagation();
                            }
                            }>
                                <Checkbox onClick={(event) => {
                                    event.stopPropagation();
                                    props.handleSelect(row);
                                }}
                                />
                            </TableCell>
                        </TableRow>
                    ))}

                </TableBody>
            </Table>
        </TableContainer>
    );
})
const SimpleTable=React.memo((道具)=>{
const classes=useStyles();
让dataLabel=generateLabel(props.columns);
函数getRowData(行){
道具。手柄箭头单击(行);
}
返回(
{dataLabel}
{props.rows.map((row)=>(
{getRowData(行)}}>
{generateRow(props.columns,row)}
{
event.stopPropagation();
}
}>
{
event.stopPropagation();
道具。手柄选择(世界其他地区);
}}
/>
))}
);
})

在应用程序组件内部,您必须使用React.memo作为
TableComponent
的功能组件,或者
使用React.PureComponent扩展它(如果是类组件)

但是,在这种情况下,必须确保在每次重新渲染时没有重新创建
updateEdge
函数。要确保这一点,请使用
useCallback
hook

另外,不要忘记向从循环中呈现的TableComponent实例添加唯一键

function App() {

    const [tableData, setTableData] = useState(null)
    const [badgeData, setBadgeData] = useState(null)

    const updateBadge = useCallback((selectedRows) {
        setBadgeData(addNewRow(selectedRows))
    }, []);

    return (
        <div>
            <HandleDataGeneration setData={setTableData}/>
            <MyBadgeComponent data={badgeData}/>
            {data.map((item) => {
                return <TableComponent key={item.id} props={item} onRowSelect={updateBadge}/>)
             })}
        </div>
    );

}
编辑:

根据您的评论代码添加工作演示Sandbox:

变化不大

  • 使用useCallback方法,并将状态更新程序转换为使用回调方法
  • 删除了JSON.parse和JSON.stringify的逻辑,而是将整个数据存储在数组中。这是因为每次使用JSON.parse时,它都会返回一个新的对象引用,因此子对象中的memo功能失败,因为它只是执行引用检查。每次组件重新呈现时,即更新徽章状态时,都会发生这种情况
  • 如果您仍然需要使用JSON.parse和JSON.stringify,请添加一个自定义比较器来深入比较数据值

如果应用程序组件是功能组件,则必须在
表格组件中使用React.memo,而不是在应用程序组件中使用useMemo;如果是类组件,则必须在
表格组件中使用React.PureComponent
对其进行扩展

但是,在这种情况下,必须确保在每次重新渲染时没有重新创建
updateEdge
函数。要确保这一点,请使用
useCallback
hook

也不要忘记添加一个唯一的密钥