I'm trying to make a React route path dynamic and for this I need to send a variable clickedSubprojectName to my routes.js.
right now my routes.js looks like this:
import React from 'react';
const Projects = React.lazy(() => import('./views/Projects'));
const Subproject= React.lazy(() => import('./views/Subproject'));
const routes = [
{ path: '/projects', exact: true, name: 'Projects', component: Projects },
{ path: "/projects/subprojects", name: 'Subproject', component: Subproject},
];
export default routes;
In my Projects.js I created a state variable which saves the name of the subproject where the user clicked on. And I want to pass this variable from my Projects class to my routes.js so that I can set the path in routes for example like this:
{ path: "/projects/"+clickedSubprojectName, name: 'Subproject', component: Subproject}
I've already tried to export a constant variable from my Projects.js like this:
export const clickedSubprojectName={
clickedSubprojectName: this.state.clickedSubprojectName}
and then imported import { clickedSubprojectName} from './views/Subproject' in my routes.js
but this isn't really working. This sets the clickedSubprojectName as the default of the state variable at the first time when the Projects component gets rendered and it doesn't get updated when the state variable changes.
Hope anyone have a solution for this problem because I haven't found anything on stackoverflow yet
Thanks
for dynamic routes.. you can use something like..
{ path: "/projects/:subproject", name: 'Subproject', component: Subproject},
and you can invoke this route by history.push("/projects" + this.state.clickedSubprojectName)
export const clickedSubprojectName={
clickedSubprojectName: this.state.clickedSubprojectName}
this definitely won't work.. this variable gets exported once and imported once. So it will always return the default value.
Related
I want to use a Html template at my Sharetribe Flex website which is build in ReactJS. I have added HomePage container, but it following error :
./src/routeConfiguration.js
Attempted import error: 'HomePage' is not exported from './containers'.
What I have tried:
I had added following code in routeConfiguration.js
const routeConfiguration = () => { return [
{
path: '/',
name: 'HomePage',
component: props => <HomePage {...props} />,
},
Pl. help me to solve this issue.
As you're exporting HomePage as default, the import in routeConfiguration.js should be import HomePage from 'containers'; - it's a common typo to put {} around the imported component and I'm guessing you may have done the same.
If not, then you need to check your env config files (babel, typescript, etc).
There are pages exported from src/containers/index.js file.
When JavaScript module bundler sees a module import with syntax like:
import { ComponentA, ComponentB } from '../containers'
it will assume that there is a file "../containers.js" or alternatively "../containers/index.js". In this case, the latter is true.
You should check Flex tutorials:
https://www.sharetribe.com/docs/tutorial-branding/add-faq-page/
I have several components. The main component is the PageTemplate.js, which describes the menu, search bar and site header. And also a place in the center for the content of other pages(functional components react).
The idea is to use the template(PageTemplate.js) on all pages of the site, since there is only one. And generate a block with content from other components (pages, ex. EditRecord.js, NewRecord.js etc).
I use a react-router and when going to /EditRecord, for example, my content block rendered edit's page(EditRecord.js) there
Now I have done it something like this:
Page transitions work and the content block generates the page I need.
but i have a huge problem. For example there is a page with a table with data(MainPage.js). And the search and search function are located in the template(PageTemplate.js). How can I transfer the state from the template(PageTemplate.js) to the page(MainPage.js) to change the data table there by search value from template? And also, if I, for example, will be on the other page(example on /NewRecord) and call teh search function in PageTemplate, then how can I tell the react, that now it is necessary to draw the main page(/) MainPage with new data by searched results?
Many thanks to all in advance;)
router code:
import { Main} from './pages/MainPage/Main';
import { EditRecordPage } from './pages/EditRecordPage/EditRecordPage';
import { NewRecord } from './pages/NewRecordPage/NewRecord';
export const routes = [
{
path: '/',
exact: true,
component: Main,
},
{
path: '/EditRecord/:id',
exact: true,
component: EditRecordPage,
},
{
path: '/NewRecord/',
exact: true,
component: NewRecord,
}
];
Code one of pages (they are identical except for the name):
import React, { useState, useEffect } from 'react';
import { PageTemplate } from '../../components/PageTemplate';
import { MainPage } from './MainPage';
export const Main = (props) => {
return (
<PageTemplate title={'Main page'} {...props}><MainPage/></PageTemplate>
)
}
Here is a chunk in the render of PageTemplate.js where the page(main, edit etc) is rendered:
<Content
className="site-layout-background"
style={{
padding: 24,
margin: 0,
minHeight: 280,
}
>
<div {...props}/>//here is the required page(main, edit, new etc)
</Content>
Is it possible to access the URL params supplied in a route outside the components?
This of course can be accomplished with window.location but I am looking for something in the react-router API to do this more cleanly.
Additionally, if there is a more standard approach to doing this with GraphQL, that's even better! I am just looking into browser clients for gql and new to gql in general.
Example component:
import React from 'react';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import get from 'lodash.get';
const ContractComponent = (props) => {
...
};
const ContractQuery = gql`query ContractQuery ($contractId: String!){
contract(id: $contractId) {
...
}
}`;
const ContractWithData = graphql(ContractQuery, {
options: { variables: { contractId: contractId } }, // <-- var i want to pull from url params
})(ContractComponent);
export default ContractWithData;
Example route:
<Route path="contract/:contractId" component={Contract} />
I'm not really familiar with react-apollo, but I think the following is a good way to achieve what you want.
You can see in the docs that options can be a function taking the component props as input, returning an object with the options: http://dev.apollodata.com/react/queries.html#graphql-options
So I think you can do:
const ContractWithData = graphql(ContractQuery, {
options: props => ({ variables: { contractId: props.params.contractId } })
})(ContractComponent);
In the code above, props.params are the params passed by react-router to the route component (nothing special there).
You want to write options as a function when you need do to something dynamic at runtime, in this case accessing the route params.
Hope it helps.
right now migrating from router v2 to v3 (feels like a deja vu). The routing configuration is now decoupled from the components again. It overthrows the logic I considered quite sensible. They have introduced a children property in the RouterConfig which gives me headache. Assume an application with many routes similar to this
/club/123/member/98/tasklist/921/edit
The route was spread over the following components with the following #Routes decorators
#Routes([{path: '/club/:id', component: DelegateClubComponent}])
export class MainApp {...}
#Routes([{path: 'user/:id', component: DelegateUserComponent}])
export class DelegateClubComponent {...}
#Routes([{path: 'tasklist/:id', component: DelegateTaskListComponent}])
export class DelegateUserComponent {...}
#Routes([{path: 'edit', component: EditTaskListComponent}])
export class DelegateTaskListComponent {...}
Each of the DelegateXComponents were responsible for resolving the respective document and making it available in a Service the other components get injected. Moreoever, all of the DelegateXComponents rendered a little template with some data of the documents they were in charge of.
How is this done with router v3 ? It makes no sense to map the entire tree in a nested RouterConfig with 5 levels of children. On the other hand, do separate RouterConfigs work at all?
export const clubRoute: RouterConfig = [
{ path: 'club/:id', component: DelegateClubComponent }];
export const userRoute: RouterConfig = [
{ path: 'user/:id', component: DelegateUserComponent }];
As long as there is no magic happening behind the scenes, how would the router know that the userRoute should be considered as a child route for clubRoute.
Confused greetings
You can define configs in the same files as the components and then just combine them to a complete tree before passing it to the router.
import {childRoutes} from './child.component'
export const clubRoute: RouterConfig = [
{ path: 'club/:id', component: DelegateClubComponent, children: childRoutes }];
I have a redux reducer loaded with several reactjs components.
I want to load these inside other components through this.props
Like: this.props.components.MyReactComponent
class OtherComponent extends Component {
render() {
const Component = this.props.components.MyReactComponent
return (
<div>
<Component />
</div>
)
}
}
Is this possible? If so, how?
EDIT The component is a connected component. I am able to load it but it is broken. In this case, it is a counter, when you click to increment or decrement nothing happens. In the console, there is this error:
Uncaught ReferenceError: _classCallCheck is not defined
if I convert the component into a dumb component (without connecting it), the error is this:
Uncaught ReferenceError: _classCallCheck3 is not defined
EDIT 2
I found out why those errors show up. It is because the react component gets stripped out when stored in the reducer:
A react component would look something like this:
{ function:
{ [Function: Connect]
displayName: 'Connect(Counter)',
WrappedComponent: { [Function: Counter] propTypes: [Object] },
contextTypes: { store: [Object] },
propTypes: { store: [Object] } } }
However, after I store it inside a reducer, it loses its properties and ends up looking something like this:
{ function:
{ [Function: Connect] } }
After reading the comments below, I thought of an alternative. I can store in a reducer the path to each component, then make a new wrapper component that could render those other components from those paths.
I tried it but encoutered a different problem with the funcion require from nodejs that for some weird reason is not letting me user a variable as an argument. For example:
This works:
var SomeContent = require('../extensions/myContent/containers')
This does not:
var testpath = '../extensions/myContent/containers'
var SomeContent = require(testpath)
Giving me the following error:
Uncaught Error: Cannot find module '../extensions/myContent/containers'.
It is adding a period at the end of the path. How can I prevent require to add that period?
If you can think of any other alternative I can implement for what I am trying to do, I would greatly appreciate it.
EDIT 3 Following Thomas advice...
What I am trying to accomplish is this:
I want to be able to render react components inside other react components, I know how to do it the same way most us know how to; however, I want to be able to do it by importing a file that would contain all the components without actually having to import and export each one of them:
OtherComponent.js
import React, { Component } from 'react'
import { SomeComponent } from '../allComponentes/index.js'
export default class OtherComponent extends Component {
render() {
return (
<SomeComponent />
)
}
}
SomeComponent.js
import React, { Component } from 'react'
export default class SomeComponent extends Component {
render() {
return (
<div>
Hello
</div>
)
}
}
allComponents/index.js
import SomeComponent from '../allComponents/SomeComponent/index.js'
export { SomeComponent }
What I am trying to do in allComponents/index.js is to avoid having import/export statements for each component by reading (with fs module) all the components inside the allComponents folder and export them.
allComponents/index.js (pseudocode)
get all folders inside allComponents folder
loop through each folder and require the components
store each component inside an object
export object
When I tried that, I encountered multiple issues, for one, export statements have to be in the top-level, and second, fs would work only on the server side.
So, that is why I thought of loading all the components in a reducer and then pass them as props. But as I found out, they got stripped out when stored them in a reducer.
Then, I thought of only storing the path to those components inside a reducer and have a wrapper component that would use that path to require the needed component. This method almost worked out but the nodejs function require wont allow me to pass a variable as an argument (as shown in EDIT 2)
I think your question is not really to do with redux but rather is (as you say):
What I am trying to do in allComponents/index.js is to avoid having import/export statements for each component by reading (with fs module) all the components inside the allComponents folder and export them.
By way of example, I have all of my (dumb) form components in a folder path components/form-components and the index.js looks something like:
export FieldSet from './FieldSet'
export Input from './Input'
export Label from './Label'
export Submit from './Submit'
export Select from './Select'
export Textarea from './Textarea'
Then when I want to import a component elsewhere, it is import { FieldSet, Label, Input, Submit } from '../../components/form-components/';