javascript - React:如何将“未定义”变量作为道具传递给组件?
问题描述
我是 reactjs 新手,这可能是基础知识,但我在互联网上找不到任何相关信息。
我有以下代码,当您单击某个按钮时会弹出一个模态窗口(单击该按钮会导致history.push(url)
动作,这会弹出模态窗口):
const ProjectBoard = () => {
const match = useRouteMatch();
const history = useHistory();
const [filters, mergeFilters] = useMergeState(defaultFilters);
const [IssueCreateModalOpen, setIssueCreateModalOpen] = useState(false);
const [{ data, error, setLocalData }, fetchProject] = useApi.get('/project');
if (!data) return <PageLoader />;
if (error) return <PageError />;
const { project } = data;
const updateLocalProjectIssues = (issueId, updatedFields) => {
setLocalData(currentData => ({
project: {
...currentData.project,
issues: updateArrayItemById(currentData.project.issues, issueId, updatedFields),
},
}));
};
return (
<Fragment>
<Header/>
<Lists
project={project}
filters={filters}
updateLocalProjectIssues={updateLocalProjectIssues}
/>
<br/>
<Route
path={`${match.path}/issues/:issueId`}
render={routeProps => (
<Modal
isOpen // confusion 1: this variable is not defined anywhere!!
testid="modal:issue-details"
width={1040}
withCloseIcon={false}
onClose={()=>history.push(match.url)}
renderContent={modal => (
<IssueDetails
issueId={routeProps.match.params.issueId}
trigger={routeProps.location.state.trigger}
projectUsers={project.users}
fetchProject={fetchProject}
updateLocalProjectIssues={updateLocalProjectIssues}
modalClose={modal.close}
/>
)}
/>
)}
/>
</Fragment>
);
}
export default ProjectBoard;
下面是Modal
定义组件的地方:
import React, { Fragment, useState, useRef, useEffect, useCallback } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import useOnOutsideClick from '../../hooks/onOutsideClick';
import useOnEscapeKeyDown from '../../hooks/onEscapeKeyDown';
const propTypes = {
className: PropTypes.string,
testid: PropTypes.string,
variant: PropTypes.oneOf(['center', 'aside']),
width: PropTypes.number,
withCloseIcon: PropTypes.bool,
isOpen: PropTypes.bool,
onClose: PropTypes.func,
renderLink: PropTypes.func,
renderContent: PropTypes.func.isRequired,
};
const defaultProps = {
className: undefined,
testid: 'modal',
variant: 'center',
width: 600,
withCloseIcon: true,
isOpen: undefined,
onClose: () => {},
renderLink: () => {},
};
const Modal = ({
className,
testid,
variant,
width,
withCloseIcon,
isOpen: propsIsOpen, // confusion 3: what does it mean, x:y ?
onClose: tellParentToClose,
renderLink,
renderContent,
}) => {
console.log('---- propsIsOpen: ', propsIsOpen, typeof(propsIsOpen))
const [stateIsOpen, setStateOpen] = useState(false);
const isControlled = typeof propsIsOpen === 'boolean';
const isOpen = isControlled ? propsIsOpen : stateIsOpen; // confusion 2: if isOpen is defined here, why even bother to pass a prop named as isOpen ??
const $modalRef = useRef();
const $clickableOverlayRef = useRef();
const closeModal = useCallback(() => {
if (!isControlled) {
setStateOpen(false);
} else {
tellParentToClose();
}
}, [isControlled, tellParentToClose]);
useOnOutsideClick($modalRef, isOpen, closeModal, $clickableOverlayRef);
useOnEscapeKeyDown(isOpen, closeModal);
useEffect(() => {
console.log('Modal renderContent: ', renderContent)
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = 'visible';
};
}, [isOpen]);
return (
<Fragment>
{!isControlled && renderLink({ open: () => setStateOpen(true) })}
{isOpen &&
ReactDOM.createPortal(
<ScrollOverlay>
<ClickableOverlay variant={variant} ref={$clickableOverlayRef}>
... some code ...
</ClickableOverlay>
</ScrollOverlay>,
$root,
)}
</Fragment>
);
};
const $root = document.getElementById('root');
Modal.propTypes = propTypes;
Modal.defaultProps = defaultProps;
export default Modal;
上面的代码段肯定有效。我只是无法理解:
混淆1:变量isOpen
在作为道具传递给Modal
组件之前没有在任何地方定义
困惑2:在组件isOpen
内被定义Modal
为“新鲜的新变量”,为什么还要首先将名为 as 的道具传递isOpen
给Modal
组件?
x:y
困惑3:组件的输入是什么意思?IEisOpen: propsIsOpen,
解决方案
在您标记“confusion1”的地方,isOpen
不是变量,而是属性名称。仅使用不带值的属性名称(just isOpen
、notisOpen="..."
或isOpen={...}
)意味着它是一个布尔属性(如checked
HTML 复选框)。如果您指定它,则该属性的值为true
。如果您不指定它,则该属性的值是undefined
(与未指定的属性一样)。
您的混淆 2 和 3 是相同的混淆:解构时,x: y
意味着“获取命名的属性x
,但将其放入一个名为的变量/常量中y
。(基本上,重命名它。)因此,解构Modal
是将其接收到的属性复制isOpen
到参数中调用propsIsOpen
. 这样,组件中的代码可以声明一个isOpen
具有略微调整值的变量。
这是一个布尔属性的示例:
function Example({theProp}) {
return <div>
<code>typeof theProp = {typeof theProp},
theProp = {JSON.stringify(theProp)}</code>
</div>;
}
ReactDOM.render(
<div>
<div><code><Example theProp/></code> :</div>
<Example theProp />
<div><code><Example /></code> :</div>
<Example />
</div>,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
这是重命名解构的示例:
const obj = {
b: 42,
};
const {b: a} = obj;
console.log(a);
推荐阅读
- javascript - AlpineJs 从 select[option] 中提取值
- html - 用 5 和 7 硬币支付任何大笔金额
- reactjs - 全局变量在 React Native 中不起作用 - Expo
- sql - 将十进制转换为日期格式 SQL
- javascript - 测试 if 路径在 angular/jasmine 中不起作用
- java - 从 Firebase 检索 ArrayList
- angular - TypeScript:复制具有匹配属性的对象
- python - 更新对象的数据成员
- makefile - 如何在配方中使用参数调用自定义函数并返回值?
- c++ - 何时复制函数参数?