将函数作为 prop 传递,调用函数时它不会获得正确的值



在我的 React 应用程序中将函数作为道具传递时,我遇到了一个奇怪的问题。 代码如下:

const NewPage = () => {
const [blocks, setBlocks] = useState([]);
const [needsShowImageModal, setNeedsShowImageModal] = useState(false);
const textButtonHandler = () => {
const key = randomInt(0, 1000000000);
const array = blocks.concat({ key, deleteButtonHandler: deleteButtonHandler });
setBlocks(array);
};
function deleteButtonHandler(blockKey) {
// Test functionality, if one text field was added arrray size should
// be 1
console.log(blocks.length);
}
return (
<div>
<ImageModal 
show={needsShowImageModal}
onHide={() => setNeedsShowImageModal(false)}
insertButtonHandler={insertImageHandler}
/>
<div className="d-flex">
<NewPageSidebar
textButtonHandler={textButtonHandler}
imageButtonHandler={imageButtonHandler}
spacingButtonHandler={spacingButtonHandler}
/>
<NewPageContent blocks={blocks} />
</div>
</div>
);
};
export default NewPage;

当调用文本按钮处理程序(按下按钮(时,我将一个新的数据模型添加到blocks数组中。我有另一个按钮处理程序deleteButtonHandler传递给NewPageContent组件(在数据模型内(。NewPageContent

const NewPageContent = ({ blocks }) => {
return (
<div className="new-page-content-container border mr-5 ml-5 p-3">
{blocks.map(block =>
<TextBlock 
key={block.key} 
blockKey={block.key}
deleteButtonHandler={block.deleteButtonHandler}
/>
)}
</div>
);
};
NewPageContent.propTypes = {
blocks: PropTypes.arrayOf(PropTypes.element)
};
export default NewPageContent;

最后这个处理程序传递给TextBlock

const TextBlock = ({ deleteButtonHandler, blockKey }) => {
const [editorState, setEditorState] = useState(
() => EditorState.createEmpty(),
);
const toolbarClickHander = (buttonType, e) => {
e.preventDefault();
switch (buttonType) {
case 'delete':
// Delete button handler called here
deleteButtonHandler(blockKey);
break;
default:
break;
}
};
return(
<div className='text-block'>
<TextBlockToolbar clickHandler={toolbarClickHander} />
<Editor 
editorState={editorState}
onChange={setEditorState}
/>
</div>
);

};

如果我通过textButtonHandler添加一个元素到blocks,则该组件将按预期呈现在屏幕上。但是,如果我点击删除按钮并调用deleteButtonHandler它会将数组的大小记录为0,奇怪的是,如果我添加第二个元素然后点击该元素的删除按钮,如果将数组大小记录为1.这几乎就像是拍摄blocks状态的快照,就像将新textButtonHandler分配给道具一样,而不是使用blocks的实际当前状态。知道我可能在这里做错了什么吗?以前没有遇到过这个问题。谢谢

好的。这里发生了什么:

在对象中传递函数。该对象可能有自己的上下文,并且您尝试在该对象上下文中使用该函数,这会使反应变得混乱。(我知道 ECMAScript 简单对象没有自己的上下文,但 react 可能会处理这些数据,所以可能会以不同的方式工作。
因此,在子组件中传递每个函数的独立道具。

示例:https://codesandbox.io/s/broken-waterfall-vgcyj?file=/src/App.js:0-1491

import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [blocks, setBlocks] = useState([
{ key: Math.random(), deleteButtonHandler }
]);
const textButtonHandler = () => {
const key = Math.random();
// const array = blocks.concat({
// key,
// deleteButtonHandler: deleteButtonHandler
// });
setBlocks(prev => prev.concat({ key, deleteButtonHandler }));
};
const deleteButtonHandler = blockKey => {
// Test functionality, if one text field was added arrray size should
// be 1
console.log(blocks.length);
};
return (
<div>
<div className="d-flex">
<NewPageContent
deleteButtonHandler={deleteButtonHandler}
blocks={blocks}
/>
</div>
<button onClick={textButtonHandler}>Handler</button>
</div>
);
}
const NewPageContent = ({ blocks = [], deleteButtonHandler = () => null }) => {
return (
<div className="new-page-content-container border mr-5 ml-5 p-3">
{blocks.map(block => (
<TextBlock
key={block.key}
blockKey={block.key}
// deleteButtonHandler={block.deleteButtonHandler}
deleteButtonHandler={deleteButtonHandler}
/>
))}
</div>
);
};
const TextBlock = ({ deleteButtonHandler = () => null, blockKey = "" }) => {
return (
<div className="text-block">
{blockKey}
<span onClick={deleteButtonHandler}>X</span>
</div>
);
};

我已经安慰了您的旧解决方案,以进行比较。

最新更新