【发布时间】:2019-11-07 09:13:15
【问题描述】:
我目前正在尝试将数据从函数传递到父组件,然后再传递到子组件。
我有一个名为 FetchUserPermissions 的函数,它查询模拟数据库并返回用户权限列表。我需要将该权限列表传递给父级根组件 App,然后再传递给限制用户查看 UI 中不同元素的能力的组件。
我真正努力做的是,将我的response 从获取请求传递给育儿组件,然后传递给其他孩子。
我的登录名和用户权限不是用户访问应用程序时看到的第一页。因此我不能从组件树的顶部传递它们。
这是我用来获取用户权限的 FetchUserPermissions 函数:
function FetchUserPermissions() {
const userRole = localStorage.getItem("role");
const accessToken = localStorage.getItem("accesstoken");
const requestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
accesstoken: accessToken,
role: userRole
}
};
if (userRole !== null) {
fetch(
process.env.REACT_APP_API_URL + "/authenticated/get-roles",
requestOptions
).then(response => response.json());
//set the response as a state.
// So that state can be passed as props to the CAN component.
} else {
console.log("not loggedin === no user permissions.");
}
}
export default FetchUserPermissions;
这是 Can 组件,旨在根据用户角色限制用户在 UI 中的视图和能力。
const check = (rules, role, action, data) => {
const permissions = rules[role];
if (!permissions) {
// role is not present in the rules
return false;
}
const staticPermissions = permissions.static;
if (staticPermissions && staticPermissions.includes(action)) {
// static rule not provided for action
return true;
}
const dynamicPermissions = permissions.dynamic;
if (dynamicPermissions) {
const permissionCondition = dynamicPermissions[action];
if (!permissionCondition) {
// dynamic rule not provided for action
return false;
}
return permissionCondition(data);
}
return false;
};
const Can = props =>
check(rules, props.role, props.perform, props.data)
? props.yes()
: props.no();
Can.defaultProps = {
yes: () => null,
no: () => null
};
export default Can;
我想也许我可以将 FetchUserPermissions 组件导出为 Context 并以这种方式传递数据,但我不知道该怎么做。
我不想做的一件事是在每次用户使用 Can 组件时调用fetch 请求,因为这会给数据库带来太大压力。
以下是 Can 组件在不同页面中的使用方式:
<div className="home">
<h1>Mock Admin Page...</h1>
<h3>{mockDataFetched}</h3>
<Can
role={userRole}
perform="dashboard-page:visit"
yes={() => (
<div>
<h1>Admin Dashboard</h1>
</div>
)}
no={() => (
<div>
<h1>Non Admin Dashboard</h1>
</div>
)}
/>
</div>
);
如果我的问题有任何不清楚的地方,我很乐意提供更多信息。提前谢谢你。
----- 编辑 -------
这是我的APP组件,它只包含一个Switch和Router元素:
function App() {
return (
<div>
{/* Where the main router is innitiated. */}
<BrowserRouter>
<div className="container">
<Header />
<Switch>
<Route exact path="/" component={Home} />
{/* custom dummy page. to be removed.*/}
<Route exact path="/page-one" component={CustomPage} />
<Route exact path="/login" component={LoginPage} />
<PrivateRoute exact path="/admin-board" component={AdminPage} />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
export default App;
-------------- 第二次编辑-------------------------------------------- ------------------------------------
应用所有建议的更改后,我不断得到:
./src/views/routes/Can.js
Line 2: 'usePermissions' is not defined no-undef
Search for the keywords to learn more about each error.
【问题讨论】:
-
你能添加你的App组件吗,所以回答会很有帮助,我认为使用上下文会是一个更好的解决方案,因为当你用上下文包装时,所有子元素都可以访问你不想要传递道具。
-
@DILEEPTHOMAS 刚刚进行了编辑并添加了 App.js 组件
-
我认为在应用程序组件中你应该有一个 ContextProvider 来包装所有路由,并且在那个 contextprovider 中你需要调用 api 并获取权限。由于在 ContextProvider 被包装,可以直接在 Can 组件级别访问权限的上下文
-
我一开始也是这么想的,只是我不知道如何具体怎么做。
-
@DILEEPTHOMAS 关于如何解决这个问题有什么建议吗?
标签: javascript json reactjs