Javascript 将函数作为道具传递,调用该函数时,它不会';无法获得正确的值
我在React应用程序中将函数作为道具传递时遇到了一个奇怪的问题。代码如下:Javascript 将函数作为道具传递,调用该函数时,它不会';无法获得正确的值,javascript,reactjs,function,react-props,Javascript,Reactjs,Function,React Props,我在React应用程序中将函数作为道具传递时遇到了一个奇怪的问题。代码如下: const NewPage = () => { const [blocks, setBlocks] = useState([]); const [needsShowImageModal, setNeedsShowImageModal] = useState(false); const textButtonHandler = () => { const key = r
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;
最后,这个处理程序被传递到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>
);
};
const TextBlock=({deleteButtonHandler,blockKey})=>{
常量[editorState,setEditorState]=useState(
()=>EditorState.createEmpty(),
);
常量工具栏ClickHander=(按钮类型,e)=>{
e、 预防默认值();
开关(按钮式){
案例“删除”:
//删除此处调用的按钮处理程序
deleteButtonHandler(区块键);
打破
违约:
打破
}
};
返回(
);
};
如果我通过
textButtonHandler
将一个元素添加到块
,组件将按预期呈现在屏幕上。但是,如果我点击delete按钮并调用deleteButtonHandler
,它会将数组大小记录为0
,奇怪的是,如果我添加第二个元素,然后点击该元素的delete按钮,如果将数组大小记录为1
。它几乎就像是在拍摄块
状态的快照,就像新的文本按钮Handler
被分配给道具,而不是使用块
的实际当前状态一样。你知道我可能做错了什么吗?我以前没有遇到过这个问题。谢谢好的。这里发生了什么:
在对象中传递函数。该对象可能有自己的上下文,并且您尝试在该对象上下文中使用该函数,这会使您感到困惑。(我知道ECMAScript simple对象没有自己的上下文,但react可能会处理该数据,因此可能以不同的方式工作。)因此,将每个函数传递给子组件中的独立属性 例如:
import React,{useState}来自“React”;
导入“/styles.css”;
导出默认函数App(){
常量[块,立根块]=使用状态([
{key:Math.random(),deleteButtonHandler}
]);
const textButtonHandler=()=>{
const key=Math.random();
//常量数组=blocks.concat({
//钥匙,
//deleteButtonHandler:deleteButtonHandler
// });
setblock(prev=>prev.concat({key,deleteButtonHandler}));
};
const deleteButtonHandler=blockKey=>{
//测试功能,如果添加了一个文本字段,则arrray大小应为
//是1
控制台.日志(块.长度);
};
返回(
处理者
);
}
const NewPageContent=({blocks=[],deleteButtonHandler=()=>null})=>{
返回(
{blocks.map(block=>(
))}
);
};
const TextBlock=({deleteButtonHandler=()=>null,blockKey=”“})=>{
返回(
{blockKey}
X
);
};
我已经将你的旧解决方案进行了比较。你能把它扔到沙箱中吗?请制作一个可生产的,看看你是不是在同一个函数中的
setBlocks
调用之后,就在控制台上记录块
?好的,是的,我明白了。基本上每次NewPage
呈现时,它都会重新创建textButtonHandler
并作为回调附加。调用textButtonHandler
时,它会包含deleteButtonHandler
的一个“实例”,该实例还包含该渲染周期中块的当前实例。调用deleteButtonHandler
的实例时,它会记录从存储模块开始的blocks.length
的值。因此,您会为每个条目传递一个delete方法。如果您编写了一个通用的delete函数,只需传入一个键、索引或id,并在根(状态存储的地方)处理该操作会怎么样?现在这就非常有意义了!谢谢我不知道为什么要在对象中传递函数。脑筋急转弯!谢谢在本例中,为什么使用concat而不是push?因为您应该始终返回一个新状态,而不是状态修改。这这可能会有所帮助:如果您返回一个经过修改的旧状态,react将不会重新启动该数组
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>
);
};
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>
);
};