使用 react-router-dom 在同一页面上进行不需要的渲染
Unwanted rendering on same page with react-router-dom
我目前正在使用 React-router-dom(React 路由器 4),我想要一个客户的详细信息页面。我可以成功获取所有数据,但数据显示在与 list/overview 相同的页面上。该图像将澄清 things.I 想要两个单独的视图。
这是路由器的结构:
const unauthenticatedPages = [
'/',
'/login'
];
const authenticatedPages = [
'/admin'
];
// public pages
const publicPage = () => {
if(Meteor.userId()) {
history.push('/');
}
};
// private pages
const privatePage = () => {
if(Meteor.userId()) {
history.push('/');
}
};
// check authentication for pages
export const onAuthenticationChange = (authenticated) => {
console.log('is authenticated...', authenticated);
const path = this.location.pathname;
const isUnauthenticatedPage = unauthenticatedPages.includes(path);
const isAuthenticatedPage = authenticatedPages.includes(path);
if( authenticated && isUnauthenticatedPage ) {
console.log('Can view the page routed to the path dashboard');
} else if (!authenticated && isAuthenticatedPage) {
console.log('No rights to view the page... routed to the path
login page');
}
}
// render app inside custom templates
const RouteWithLayout = ({layout, component, ...rest}) => {
return (
<Route {...rest} render={ (props) => React.createElement( layout, props, React.createElement(component, props)) } />
);
};
export const routes = (
<BrowserRouter>
<Switch>
<RouteWithLayout exact path="/" layout={AuthenticationLayout} onEnter={publicPage} component={AuthLogin} />
<RouteWithLayout path="/login" layout={AuthenticationLayout} onEnter={publicPage} component={AuthLogin} />
<AdminLayout>
<Route path="/admin" component={AdminDashboard} />
<Route path="/klanten/:customerID" component= . {CustomerDetails} />
<Route path="/klanten" component={CustomerOverview} />
<Route path="/nieuwe-klant" component={CustomerCreate} />
</AdminLayout>
<Route path="*" component={PageNotFound} />
</Switch>
</BrowserRouter>
);
额外信息:
这个路由器还有一些问题。我使用了 alanning:roles 因为用户必须根据他们的角色成为路由器。该图像显示了管理区域,但用户将使用选项较少的模拟布局。我怎样才能做到这一点?
如果我使用像 /new-customer/ 这样的单独路由,我会看到一个只有表单的新页面,但我想使用 /customer/new/ 作为路由。如果我将路由更改为 /customer/new/ 我的页面将不会呈现。
/new-customer/ 页面的代码:
class CustomerCreate extends Component {
constructor(props) {
super(props);
this.state = {
message: ''
};
}
onFormSubmit(event) {
event.preventDefault();
const relationNumber = this.refs.relationNumber.value;
const companyName = this.refs.companyName.value;
const locationStreet = this.refs.locationStreet.value;
const locationPostal = this.refs.locationPostal.value;
const locationCity = this.refs.locationCity.value;
const contactPersonName = this.refs.contactPersonName.value;
const contactPersonEmail = this.refs.contactPersonEmail.value;
const contactPersonPhone = this.refs.contactPersonPhone.value;
const password = this.refs.password.value;
const confirmPassword = this.refs.confirmPassword.value;
const checkEmail = (email) => {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const validated = regex.test(email);
return validated;
};
const checkPassword = ( pwd, pwd2 ) => {
if( pwd != '' || pwd2 != '' ){
if ( pwd.length >= 5 ) {
if ( pwd === pwd2 ) {
return true;
} else {
return false;
}
} else {
return false;
}
}
};
const validatedEmail = checkEmail( contactPersonEmail );
const validatedPassword = checkPassword( password, confirmPassword
);
if(!validatedEmail) {
this.setState({message: 'Het e-mailadres is niet correct.'});
}
if(!validatedPassword ) {
this.setState({message: 'De wachtwoorden komen niet overeen!'});
}
if( validatedEmail && validatedPassword ) {
try {
const createdAccount = Accounts.createUser({
email : contactPersonEmail,
password : password,
relationNumber : relationNumber,
companyName : companyName ,
locationStreet : locationStreet,
locationPostal : locationPostal,
locationCity : locationCity,
contactName : contactPersonName,
contactPhone : contactPersonPhone,
isArchived : 0,
setRoles : ['customer']
});
this.setState({message: 'De klant is succesvol toegevoegd!'});
// send flashmessage of succesfull state
return createdAccount;
} catch( err ) {
return err.reason;
}
}
return false;
}
render() {
return (
<div>
form sitting here ...
</div>
);
}
}
export default CustomerCreate;
因为两条路线都匹配klanten
。尝试将客户端详细信息路径重命名为 kunde
。或者,正如其他人所建议的那样,将 exact
属性 添加到 klanten 概述路径中。
要回答问题 2,请在您的开关中将 customer/new
放在 customer/:id
之前。并确保客户永远不会拥有 'new' 的 ID。
现在 React-Router 正在首次渲染:
<Route path="/klanten/:customerID" component= . {CustomerDetails} />
然后:
<Route path="/klanten" component={CustomerOverview} />
当您转到任何包含 /klanten 的路径时。
重命名两条路线之一或添加 exact={true} 如下:
<Route path="/klanten/:customerID" component= . {CustomerDetails} exact={true} />
Switch 组件仅呈现它的一个 直接 子组件。因为您的 /klanten
和 /klanten/:customerID
路由不是组件的直接子级,所以只要路由与 /klanten*
匹配,它们都会呈现
您可以在 /klanten
路线上使用 exact
属性,这样它就不会匹配 /klanten/:customerID
路线。
<Route path="/klanten/:customerID" component= . {CustomerDetails} />
<Route path="/klanten" exact component={CustomerOverview} />
我目前正在使用 React-router-dom(React 路由器 4),我想要一个客户的详细信息页面。我可以成功获取所有数据,但数据显示在与 list/overview 相同的页面上。该图像将澄清 things.I 想要两个单独的视图。
这是路由器的结构:
const unauthenticatedPages = [
'/',
'/login'
];
const authenticatedPages = [
'/admin'
];
// public pages
const publicPage = () => {
if(Meteor.userId()) {
history.push('/');
}
};
// private pages
const privatePage = () => {
if(Meteor.userId()) {
history.push('/');
}
};
// check authentication for pages
export const onAuthenticationChange = (authenticated) => {
console.log('is authenticated...', authenticated);
const path = this.location.pathname;
const isUnauthenticatedPage = unauthenticatedPages.includes(path);
const isAuthenticatedPage = authenticatedPages.includes(path);
if( authenticated && isUnauthenticatedPage ) {
console.log('Can view the page routed to the path dashboard');
} else if (!authenticated && isAuthenticatedPage) {
console.log('No rights to view the page... routed to the path
login page');
}
}
// render app inside custom templates
const RouteWithLayout = ({layout, component, ...rest}) => {
return (
<Route {...rest} render={ (props) => React.createElement( layout, props, React.createElement(component, props)) } />
);
};
export const routes = (
<BrowserRouter>
<Switch>
<RouteWithLayout exact path="/" layout={AuthenticationLayout} onEnter={publicPage} component={AuthLogin} />
<RouteWithLayout path="/login" layout={AuthenticationLayout} onEnter={publicPage} component={AuthLogin} />
<AdminLayout>
<Route path="/admin" component={AdminDashboard} />
<Route path="/klanten/:customerID" component= . {CustomerDetails} />
<Route path="/klanten" component={CustomerOverview} />
<Route path="/nieuwe-klant" component={CustomerCreate} />
</AdminLayout>
<Route path="*" component={PageNotFound} />
</Switch>
</BrowserRouter>
);
额外信息: 这个路由器还有一些问题。我使用了 alanning:roles 因为用户必须根据他们的角色成为路由器。该图像显示了管理区域,但用户将使用选项较少的模拟布局。我怎样才能做到这一点?
如果我使用像 /new-customer/ 这样的单独路由,我会看到一个只有表单的新页面,但我想使用 /customer/new/ 作为路由。如果我将路由更改为 /customer/new/ 我的页面将不会呈现。
/new-customer/ 页面的代码:
class CustomerCreate extends Component {
constructor(props) {
super(props);
this.state = {
message: ''
};
}
onFormSubmit(event) {
event.preventDefault();
const relationNumber = this.refs.relationNumber.value;
const companyName = this.refs.companyName.value;
const locationStreet = this.refs.locationStreet.value;
const locationPostal = this.refs.locationPostal.value;
const locationCity = this.refs.locationCity.value;
const contactPersonName = this.refs.contactPersonName.value;
const contactPersonEmail = this.refs.contactPersonEmail.value;
const contactPersonPhone = this.refs.contactPersonPhone.value;
const password = this.refs.password.value;
const confirmPassword = this.refs.confirmPassword.value;
const checkEmail = (email) => {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const validated = regex.test(email);
return validated;
};
const checkPassword = ( pwd, pwd2 ) => {
if( pwd != '' || pwd2 != '' ){
if ( pwd.length >= 5 ) {
if ( pwd === pwd2 ) {
return true;
} else {
return false;
}
} else {
return false;
}
}
};
const validatedEmail = checkEmail( contactPersonEmail );
const validatedPassword = checkPassword( password, confirmPassword
);
if(!validatedEmail) {
this.setState({message: 'Het e-mailadres is niet correct.'});
}
if(!validatedPassword ) {
this.setState({message: 'De wachtwoorden komen niet overeen!'});
}
if( validatedEmail && validatedPassword ) {
try {
const createdAccount = Accounts.createUser({
email : contactPersonEmail,
password : password,
relationNumber : relationNumber,
companyName : companyName ,
locationStreet : locationStreet,
locationPostal : locationPostal,
locationCity : locationCity,
contactName : contactPersonName,
contactPhone : contactPersonPhone,
isArchived : 0,
setRoles : ['customer']
});
this.setState({message: 'De klant is succesvol toegevoegd!'});
// send flashmessage of succesfull state
return createdAccount;
} catch( err ) {
return err.reason;
}
}
return false;
}
render() {
return (
<div>
form sitting here ...
</div>
);
}
}
export default CustomerCreate;
因为两条路线都匹配klanten
。尝试将客户端详细信息路径重命名为 kunde
。或者,正如其他人所建议的那样,将 exact
属性 添加到 klanten 概述路径中。
要回答问题 2,请在您的开关中将 customer/new
放在 customer/:id
之前。并确保客户永远不会拥有 'new' 的 ID。
现在 React-Router 正在首次渲染:
<Route path="/klanten/:customerID" component= . {CustomerDetails} />
然后:
<Route path="/klanten" component={CustomerOverview} />
当您转到任何包含 /klanten 的路径时。
重命名两条路线之一或添加 exact={true} 如下:
<Route path="/klanten/:customerID" component= . {CustomerDetails} exact={true} />
Switch 组件仅呈现它的一个 直接 子组件。因为您的 /klanten
和 /klanten/:customerID
路由不是组件的直接子级,所以只要路由与 /klanten*
您可以在 /klanten
路线上使用 exact
属性,这样它就不会匹配 /klanten/:customerID
路线。
<Route path="/klanten/:customerID" component= . {CustomerDetails} />
<Route path="/klanten" exact component={CustomerOverview} />