I'm having some difficulty passing data that I have mapped from an API, it displays a bunch of Event cards based on how many events there are in the API array.
This my Event Cards component;
export default function EventCard() {
const classes = useStyles();
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await axios("http://localhost:23455/Event");
setData(result.data);
};
fetchData();
}, []);
const handleClick = (value) => () => {
console.log(value);
};
return (
<div>
<Row>
{" "}
{data.map((item) => (
<Card
className={classes.root}
style={{ marginRight: "25px", marginBottom: "25px" }}
>
<CardHeader
avatar={
<Avatar aria-label="recipe" className={classes.avatar}>
{item.icon}
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={item.name}
subheader="September 14, 2016"
/>
<CardMedia
className={classes.media}
image={LordsLogo}
title="Paella dish"
/>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
<p key={item.id}> {item.description}</p>
<p key={item.id}> {item.startDate}</p>
<p key={item.id}> {item.endDate}</p>
</Typography>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<Button variant="outlined">Steward</Button>
</IconButton>
<IconButton aria-label="share">
<Button variant="outlined" onClick={handleClick({ item })}>
Tickets
</Button>
</IconButton>
</CardActions>
</Card>
))}
</Row>
</div>
);
}
I have an onclick function which logs what data is being added into "value" onclick, if I click a card, the console log the value of that specific card:
What I'm trying to do now is use this information in another component called ServiceForm. I want to be able to click the button, be linked to ServiceForm, and use the variables within "Item" in the ServiceForm component, Ideally as shown below;
<Form.Group as={Col} controlId="formGridForeName">
<Form.Label>**{item.description}**</Form.Label>
<Form.Control
name="firstName"
placeholder="Enter name"
onChange={this.handleChange}
/>
</Form.Group>
EventCard if a functionalComponent and ServiceForm is a class based component, how could I pass the information from the first to the latter? Thanks
Edit: To show component hierarchy
ServiceForm is rendered in ServiceApplication, as shown:
import * as React from "react";
import { ServiceForm } from "../components/ServiceForm";
class ServiceApplication extends React.Component {
render() {
return (
<React.Fragment>
<h1>Service Application</h1>
<h6>Users can use this page to apply for tickets.</h6>
<ServiceForm />
</React.Fragment>
);
}
}
export default ServiceApplication;
EventCard component is rendered in EventsPage, as shown below;
import EventCard from "../components/EventCards/EventCard";
class EventsPage extends React.Component {
render() {
return (
<React.Fragment>
<h1>Events</h1>
<h6>
Welcome to the Events, here you can apply for seats or tickets at the
events shown below.
</h6>
<Row>
<EventCard />
</Row>
</React.Fragment>
);
}
}
export default EventsPage;
The idea is to pass on the ID when Clicking the 'Tickets' button on the EventCard (the ID is being pulled from an API and mapped).
It's a question of how you want to store state in your app really.
Take a simple example where a component which is a child of another. In that case, the parent can store the state locally e.g. useState() and pass it down as props to the child.
const SomeParent = () => {
const [isTrue, setIsTrue] = React.useState(true)
return (
<Child isTrue={isTrue} />
)
}
There may be cases where you want to share state across multiple components, or across your whole app. In that case, you have a load of different options.
1. Lifting state up to the highest point you need.
It would be easiest to move your state which is shared between multiple components up to the highest point that the two components share.
e.g.
Section component <- store state here
Parent one
child one
child two
Parent two
child one
Here you can again either useState() or alternatively store the state in a useReducer() and pass dispatch down.
The data flow would then look something like this:
initialise state in the section component e.g. const [someState, setSomeState]
pass the setSomeState callback down to the Parent component and in turn child component as a prop e.g.
In the child component set state onClick using the callback e.g. onClick = {() => action(item)}
pass the state value down to your second Parent component and in turn child component e.g.
You have access to the state in your form
This can be an object or multiple state values. As complexity increases, I tend to reach for useReducer().
2. Implementing useContext OR Redux in your application to create an application state accessible from any component (This is a much bigger explanation and there are lots of resources on each...
NOTE: I'm not sure why you're using two sets of brackets here:
const handleClick = (value) => () => {
console.log(value);
};
and when you're calling handleClick you need to switch it for an arrow function if you're passing a value:
onClick={handleClick({ item })
...
onClick={() => handleClick(item)}
Try this:
const handleClick = (value) => {
console.log(value);
};
<Button variant="outlined" onClick={() => handleClick({ item })} />
basically, you want to trigger a class component function from a functional component by passing item prop, if it was a parent child components you can pass a function as a prop and trigger it whenever you want from your parent or child component.
but in your case both components are not connected, what you can do without using redux is to create a public local storage for ex let's call it localStorage.js :
var PublicData = (function() {
var data = null;
var getData = function() {
return data;
};
var setData = function(props) {
data = props;
};
var clearData = function() {
data = null;
};
return {
GET: getData,
SET: setData,
CLEAR: clearData
}
})();
export default PublicData;
then you import it and use like the following :
import PublicData from './PublicData.js';
PublicData.SET(apiData); // you set your data once you fetch it
const data = PublicData.GET(); // get data
PublicData.CLEAR(); // clear your data
Note : this is not an actual localStorage, but it work the same, it will help you to share variables between your components.
Parent
/ \
Service Event
I'm guessing from your question that a simplification of your app tree looks like the above.
The problem you are having is the following:
Parent
/ \
Service Event
Data
In a top down architecture Service does not know about Event and any data over there in the that branch.
So you have 2 options (likely more, but these 2 get you a long way):
Hoist the data
Parent
Data
/ \
Service Event
Store the data somewhere else and provide a mechanism for access
Data
Parent
/ \
Service Event
Option 1 can be achieved by passing props (the data) and functions (passed using props) to manipulate the data (or, indeed, populate it in the first place i.e. fetch it)
The flow would look something like:
Parent is stateful. Parent passes the current state of the data to children that care about it (in your case that looks like Service and Event). Parent passes a function to Event, which can be attached to a click handler within the Event subtree of elements.
Due to passing a function down, when that click handler is invoked it can set the state of the Parent, from which the normal top-down rendering flow will handle setting updates and passing the data changes down the tree, whereby they will (usually) invoke a re-render.
I think Recoil uses this method, and it is becoming increasing popular once more as we look to split applications up and eschew global state management.
Option 2 is where data management libraries like Redux, Cerebral, MobX et al live. If you’re familiar with the publisher/subscriber pattern then you'll know how they work.
In essence, these libraries hold shared state for your application, such as the data you have here. They then (typically) provide a pattern for you to manage changes to the state (via a published event) and ensure that components that subscribe to that data receive the new state and update.
The 'discussion' here differs from option 1:
The click handler publishes an event, which, in essence, asks for some manipulation to the data. Manipulation occurs (or not), and subscribers are updated. In your case, the click would tell the centralised store/s (i.e. anything listening) to fetch the data, when it is done and the data is changed (from empty to filled) it lets all concerned elements (or, quite possibly, the entire application tree and leverage top-down rendering) know about it and they can do what they need to do.
Which option you pick is entirely up to you, they both have pros and cons.
Good luck thinking about your data, how you store it, and how you use it!
I'm glad you asked this question because this is a problem that has been faced and solved a lot of the times. Other contributors have written nice comprehensive answers so I'll keep it short.
1. Move shared stated to a common ancestor.
This one's pretty straight forward but gets very hairy very quickly.
2. Use Context API
You can use react's context API to move code responsible for fetching data to your context and use that data anywhere in your app without a lot of hassle. This approach is getting quite popular nowadays. Take a look at this and here's a sweet library to help you get started.
3. Use a state management library (preferred)
You can choose to use any state management library you like to solve this problem. There are quite a few options, and redux is the most popular one and for a very good reason. It enables you in implementing separation for concern between your data and your UI, but is a bit verbose.
Mobx is also popular and has a good developer experience but I personally don't like that it enforces a certain style to your code.
If you're new to react and state management then these libraries could be really daunting. I'd suggest you start with zustand. It's super simple and gets the job done. ;)
You can simply use Custom Event https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent. It is not the best practice but it work.In EventCard, when user click you dispatch a Custom event with payload is item, then ServiceForm will listener that event and store item as state. Working demo here
https://codesandbox.io/s/distracted-aryabhata-ec6gc
EventCard
const handleClick = () => {
const item = {
description: "This is description"
};
const event = new CustomEvent("customEvent", {
detail: item
});
window.dispatchEvent(event);
};
Service Form
const [item, setItem] = useState(null);
...
useEffect(() => {
const handler = (e) => {
setItem(e.detail);
};
window.addEventListener("customEvent", handler);
return () => window.removeEventListener("customEvent", handler);
}, []);
Related
If we use useMemo to memoize child components say an array of individual book to prevent re-rendering. Wouldn't it effect the performance of the app by consuming more memory to save the states?
Child-
const Book = ({ item }) => {
return useMemo(() => {
console.log(item.name);
return (
<div>
<p>{item.name}</p>
<p>{item.author.name}</p>
</div>
);
}, [item]);
};
Parent-
const Books = (props) => {
const books = props.data.books.map((item) => {
return <Book key={item.id} item={item} />;
});
return (
<>
<div>
<button
onClick={() => {
console.log("render button");
props.func();
}}
>
Add new
</button>
<div>{books}</div>
</div>
</>
);
};
If the props.data.books array is huge in size then, Wouldn't it effect the performance of the app by consuming more memory to save the states?
What is the industry practice? Does facebook use useMemo for a post/story?
React hook useMemo should be used for preventing expensive re-renders. Your Book component is very cheap to render, as it basically do nothing but show some data, which already are stored in memory. And Book component is provided with key attribute, so there is no problem for React to render many of them, unless you need to show at least thousands of them at once.
Expensive render could mean counting derived data - statistics, graphs etc. If such operations are needed, you may consider using data store instead (like Redux + Relect)
There is no sharp line when useMemo should be used. As you expected, it can do more hurt than good.
https://beta.reactjs.org/apis/react/useMemo
I am having some OOP issues that are probably pretty simple. I have a class that renders some html. However it has an onClick that calls a function that sets a flag inside the class if the image is clicked. Now here is the issue, when I render this class object and click the button from a separate js file, it stays false. I want it to permanently change the flag to true when clicked. here is the class...
class Settings extends React.Component {
handleClick() {
this.flag = true;
console.log(this.flag)
}
render(){
return(
<img src="./img/leaf.png" alt="" onClick={() => this.handleClick()}/>
);
}
}
and here is the code that calls it from a separate file...
const settingsObj = new Settings();
console.log(settingsObj.flag);
I want the flag to be false until the button is clecked and then it permamently changes to true. But it only goes true until my page rerenders as new data comes in and it resets to false. I have tried constructors and a few other techniques with no success.
Normal OOP design principles don't always apply directly to React components. Components don't usually have instance properties, they mostly just have props and state (there are a few exceptions where you do use an instance property, like Animation objects in react-native, but these are rare).
You're kind of mixing the two things in a way that doesn't quite make sense here. Settings is a React component that renders an image, but it's also an object which you instantiate by calling new Settings(). If there are other components which depend on the value of flag, you might want to separate the accessing and storing of the flag from the render component, passing a value and a callback to the renderer.
const Settings = ({setFlag}) => {
return(
<img src="./img/leaf.png" alt="" onClick={() => setFlag(true)}/>
);
}
You've suggested that you like the Context API as a solution for making the flag value globally available. There are a few ways to set this up, but here's one.
Outside of any component, we create a FlagContext object that has two properties: a boolean value flag and callback function setFlag. We need to give it a default fallback value, which is hopefully never used, so our default callback just logs a warning and does nothing.
const FlagContext = createContext<FlagContextState>({
flag: false,
setFlag: () => console.warn("attempted to use FlagContext outside of a valid provider")
});
This FlagContext object gives up Provider and Consumer components, but it's up to us to give a value to the FlagContext.Provider. So we'll create a custom component that handles that part. Our custom FlagProvider uses a local state to create and pass down the value. I've used a function component, but you could use a class component as well.
const FlagProvider = ({children}) => {
const [flag, setFlag] = useState(false);
return (
<FlagContext.Provider value={{
flag,
setFlag
}}>
{children}
</FlagContext.Provider>
)
}
We want to put the entire App inside of the FlagProvider so that the whole app has the potential to access flag and setFlag, and the whole app gets the same flag value.
When you want to use the value from the context in a component, you use either the useContext hook or the Consumer component. Either way, I like to creating an aliased name and export that rather than exporting the FlagContext object directly.
export const FlagConsumer = FlagContext.Consumer;
export const useFlagContext = () => useContext(FlagContext);
With the Consumer, the child of the consumer is a function that takes the value of the context, which in out case is an object with properties flag and setFlag, and returns some JSX.
This is usually a function you define inline:
const SomePage = () => {
return (
<FlagConsumer>
{({flag, setFlag}) => (<div>Flag Value is {flag.toString()}</div>)}
</FlagConsumer>
)
}
But it can also be a function component. Note that when using a function component as the child, you must pass the component itself ({Settings}) rather than an executed version of it (<Settings />).
const Settings = ({ setFlag }) => {
return <img src="./img/leaf.png" alt="" onClick={() => setFlag(true)} />;
};
const SomePage = () => {
return <FlagConsumer>{Settings}</FlagConsumer>;
};
The preferred method nowadays is with hooks. We call useFlagContext() inside the body of the function component and it returns our context object.
const SomePage = () => {
const {flag, setFlag} = useFlagContext();
return <Settings setFlag={setFlag}/>
};
Both the consumer and the hook only work if they are inside of a flag context provider, so that's why we put it around the whole app!
const App = () => {
return (
<FlagProvider>
<SomePage />
</FlagProvider>
);
};
Complete example on CodeSandbox
For this kind of interactions, I highly recommend you to use Redux
Another think I'm sure you will benefit from, is switching to hooks and function components: less boilerplate and much flexible code.
Back to the goal, using Redux your code would look similar to this:
const Settings = (props) => {
const dispatch = useDispatch();
const flag = useSelector(state => state.yourStoreObj.flag);
handleClick() {
dispatch(yourCustomAction("UPDATE_FLAG", true));
}
return(
<img src="./img/leaf.png" alt="" onClick={() => handleClick()}/>
);
}
Explanation:
First of all, spend 15 mins and get used to React Redux. Here's a good practical article to start with. If you're not familiar with hooks, start learning them as that will change a lot, while you don't need to change a single line of what you've done so far.
We suppose there's a property in the store that is the "flag" property of that specific element. In this way, the property can be read by the component itself with the useSelector() operator, or can be read anywhere in your application with the same methodology from any other component.
In the same way, you can change the value by dispatching a change (see dispatch() function) and in the same way, you can do that from any other components.
So, let's say you want to change that property when a click occurs on a completely different component, this is how the other component may looks like
const OtherCoolComp = (props) => {
const dispatch = useDispatch();
handleClick() {
dispatch(yourCustomAction("UPDATE_FLAG", true));
}
return(
<button onClick={() => handleClick()}>
Click me!
</button>
);
}
So you're dispatching the same action, setting it to the value you prefer, from a component that doesn't know who is displaying that value.
I'm working on a React component library that allows for client-side data filtering by passing an array of objects and an <input/> as props to a <SearchFilter/> component. I want to return the filtered results to a separate <SearchResults/> component that can be rendered elsewhere in the tree (i.e. the results component doesn't have to be a child of the input component).
I've got the filtering figured out, but I'm not sure the best route to take in React on getting the filtered data to the <SearchResults/> component.
This is what I'd like to end up with...
<SearchFilter
data={data}
input={<input type="text" value={value} onChange={this.handleChange}/>}
/>
Then, using Render Props to return the data and map over that to return JSX, there would be the results component. Something like this...
<SearchResults
render={data => (
data.map(el => (
<div>
<span>{data.someProperty}</span>
</div>
)
)}
/>
This is what I'd like to achieve because I want to allow for rendering the <SearchFilter/> component at one place in the tree, and allow the <SearchResults/> component to be rendered elsewhere, so that there's maximum flexibility in how the tree is composed and, therefore, how the view is rendered.
I've looked into the Context API, but it seems like that would require a handful more components to be a part of my library, which further complicates what I'm trying to achieve. If that's the only way around it, then that's fine, but I wanted to ask and see if anyone can think of another solution.
Thanks!
The bigger issue is that you will need to manage a state that is shared between components on a higher level, i.e., any component that will wrap these other two components, ultimately. With plain React, this state would be managed by the parent (or ancestor) component, passing down the relevant values as props. This opposed to the, usually bad, idea to have sibling components influence each other's state, since you well get into the "who's boss here"-problem.
The thing the Context API handles is not having to pass down props for things that typically don't change (or: typically shouldn't cause renders to trigger often).
A global state store, such as Redux, can help you modelling this, but in essence it's not much more than 'a' component managing state, and other components rendering according to that state. Events within the lower components trigger changes in the data, which will cause the state to change, which will cause the props of the children to change, which then will cause re-renders.
I'd advise you to try using this simple pattern:
class Search ... {
state = {data: [], text: ""}
render() {
return (
<div>
<SearchFilter
data={this.state.data}
onSearch={() => this.fetchNewData()}
onChange={(e) => this.setState({text: e.targetElement.value})}
text={this.state.text}
/>
<SearchResults data={this.state.data} />
</div>
);
}
fetchNewData() {
fetch('/url?text=' + this.state.text)
.then((newData) => { this.setState({data: newData}); })
}
}
Something along these lines. If you have trouble modelling stuff like this, you can use Redux to force you to do it in a similar way, and avoid managing local state intermixing with global state (which is typically something that is hard to manage).
If you do this right, components that have no state (i.e., aren't responsible for managing state and thus have no event handlers) can all become pure components, i.e. stateless components, i.e. functions that return JSX based on props:
const SearchResults = ({data}) => <div>{data.map( () => <etc /> )}</div>
You could create a data store class that holds your filter, pass it in as a property to both components, and have your SearchFilter component change a value in that.
I need to listen to following events and do action accordingly
Form submit event - if the form submission is successful, I need to broadcast success event Added Name Record and submit the data along with it to 3rd party service. If not, I need to broadcast a failed event say Name submission failed along with where the error occurred.
Page visit/Route Change - Self explanatory
Click events - Can be from list item click and button click. In case of list item need to pass item details and in case of button just the name maybe
Searches - Any searches made should fire the event sending the keyword.
I am using React - 0.13 and Reflux store.
How can I approach towards it to handle the events at a global level and without writing code at each button click/submit event/search etc ?
What is the best approach ? Body handler won't be enough I feel for this level of customisation required!
P.S - When I say broadcast let's assume that I have a 3rd party function call to make instead.
Purely React ways:
Create base components to globally handle events with extensible event handling methods:
const MyForm = ({ onSubmit, children, ...props }) => (
<form {...props} onSubmit={evt => {
// do global handling
onSubmit(evt);
}}>
{children}
</form>
);
//use case
const CustomForm = () => (
<MyForm onSubmit={evt => /* custom handling */}>
{/* CustomForm inputs and such */}
</MyForm>
)
Alternatively, you could take the HOC approach and wrap each handler you need:
const MyFormHOC = FormComponent => {
return class extends React.Component {
render() {
const { onSubmit, ...props } = this.props;
return (
<FormComponent {...props} onSubmit={evt => {
// do global handling
onSubmit(evt);
}}/>
}
}
};
//use case
let CustomForm = ({ onSubmit, ...props }) => (
<form onSubmit={evt => onSubmit(evt)}>
{/* CustomForm inputs and such */}
</form>
);
CustomForm = MyForm(CustomForm);
Downside to HOC approach is that your components need to pass along the event handler to the DOM element that will ultimately call it.
You could go one step further and create a single base component or HOC that handles all of your global events and then start using that as needed on your other components. It would need to know which props are supported by what components, though (e.g., onSubmit doesn't belong on anything besides a form).
I want to implement this structure in the page:
1. Cards with summary (revenue, users, etc.)
2. Map from google maps
3. List element
Inside List element there is filtering. I am stuck how to user filter options when filtering list to represent filtered information in the map and cards.
As #trixn recommended I am using this structure:
// app.js
<Admin restClient={jsonServerRestClient('http://jsonplaceholder.typicode.com')}>
<Resource name="posts" list={MyCustomPostList} /* other views */ />
</Admin>
// MyCustomPostList.js
class MyCustomPostList extends React.Component {
render() {
const {myOwnProp, ...otherProps} = this.props;
return (
<div>
// render your own components here
<AnyComponent myOwnProp={myOwnProp} />
<AGoogleMapsComponent />
// render the normal <List> component
<List {...otherProps}>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<TextField source="body" />
</Datagrid>
</List>
</div>
);
}
}
Now I am failing to send required data to Maps and AnyComponent.
So I either have to pass same data to Maps and AnyComponent or somehow synchornize filters that are being used in the List component.
How shall I achieve this?
Thank you! I would know how to connect new actions. But I am lost how to connect to already used actions to pass Filter options to Maps and AnyComponent, so I could show relevant information there, which should update its state after Filters are being triggered in List component.
You do not connect to actions. You dispatch them to alter the state of the redux store. It is important that you fully understand the concepts of redux otherwise it will be very hard for you to build this kind of custom app. To make sure data is only flowing from top to bottom components can only listen to changes of the store and not to actions.
So basically you have two options:
1. Create your own <List> component
Quoted from the admin-on-rest docs:
Admin-on-rest was build with customization in mind. You can replace any admin-on-rest component with a component of your own, for instance to display a custom list layout, or a different edition form for a given resource.
If you only want to display your additional elements in your list view you can wrap the <List> component instead of the <Resource> component. The <List> component receives the entities in a prop "data" and the filtered ids in a prop "ids". You can use that to display it in your own component. E.g. if you want to manage a list of locations and show a google map inside the list component:
import React from 'react';
import { List } from 'admin-on-rest';
const LocationsList = props => (
// render your own components
<MyGoogleMapsComponent data={this.props.data} ids={this.props.ids}>
// render the admin-on-rest <List> component
<List {...props}>
// render the DataGrid
</List>
);
Then you can pass your custom list to the <Resource> component:
<Admin>
<Resource name="locations" list={LocationList} />
</Admin>
When you filter your locations in the list the updated query will be passed to your <LocationList> and it will re-render with the new locations. But remember that this will only show your google map inside the list view of your admin page.
2. Connect your component to the redux store.
Do this only if you want your component, e.g. the google map, to be displayed outside of your list view. This one is much more advanced as you will need to learn a lot more about the internals of admin-on-rest. You will have to connect your custom component to the redux store. You can do that with the connect() function from the react-redux package:
// in MyGoogleMapsComponent.js
import React from 'react';
import { connect } from 'react-redux';
const LocationMap = ({locations}) => (
//render something based on the props
);
const mapStateToProps = (state, props) => {
// state.admin contains all the registered resources with their name as a key
const locationsResource = state.admin.locations;
// every resource has a "data" object with all entities mapped by id
const allLocations = locationsResource.data;
// every resource has a "list" object that has an array of ids of the currently filtered entities
const filteredIDs = locationsResource.list.ids;
return {
locations: filteredIDs.map(id => allLocations[id]),
};
};
// connect your component to the store
export default connect(mapStateToProps)(LocationsList)
mapStateToProps is a function that takes the current state in your store and the props of your component and returns an object containing additional props to be passed to your component.
Also this approach uses internals of the implementation of the admin-on-rest components. Some of the props you'll need to use are not part of the api and could in the worst case suddenly change in which case your app may not work anymore if you update to a new version of admin-on-rest. So keep in mind you may need to update your implementation when breaking changes occur.
If you only want to access the filters itself, they are stored in every resource under yourResourceName.list.params.filter with the name of the filter as the key and the value as the value...
Hint: If you want to see, how data inside the store of an admin-on-rest app ist stored in a real life example install the Redux DevTools for google chrome and open the admin-on-rest demo. You can then open the inspection bar and there will be a new tab redux where you can see the contents of the redux store and all the actions that get dispatched when interacting with the app. This way you it will be much easier to understand how admin-on-rest works.
The List component exported by admin-on-rest is connected with redux and receive the filters from state. You should do the same. See the code of the List component, espcially the mapStateToProps function:
The List component exported by admin-on-rest is connected with redux and receive the filters from state. You should do the same. See the code of the List component, espcially the mapStateToProps function:
Something like:
// MyCustomPostList.js
import { connect } from 'react-redux';
import { parse } from 'query-string';
class MyCustomPostList extends React.Component {
render() {
const { myOwnProp, query: { filter }, ...otherProps } = this.props;
return (
<div>
// render your own components here
<AnyComponent filter={filter} myOwnProp={myOwnProp} />
<AGoogleMapsComponent filter={filter} />
// render the normal <List> component
<List {...otherProps}>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<TextField source="body" />
</Datagrid>
</List>
</div>
);
}
}
const getLocationSearch = props => props.location.search;
const getQuery = createSelector(
getLocationSearch,
(locationSearch) => {
const query = parse(locationSearch);
if (query.filter && typeof query.filter === 'string') {
query.filter = JSON.parse(query.filter);
}
return query;
},
);
function mapStateToProps(state, props) {
return {
query: getQuery(props),
};
}
export default connect(mapStateToProps)(MyCustomPostList);