react-admin: <Show> component elements not rendering when wrapped inside divs - javascript

I'm currently working on an admin portal using react-admin, and I've been able to seamlessly style it using MaterialUI, specifically its makeStyles hook. The way I've done it is I'd import my makeStyles file that looks similar to this:
export const detailsView = makeStyles({
detail: {
width: "100%",
"& div": {
display: "Block",
visibility: "Visible",
}
}
export default detailsView
into my main component, that would hold, for example, a List component like this:
export const ExampleList = (props) => {
const classes = importedStyles();
return (
<>
<h2 className={classes.tableTitle}>Example Header</h2>
<List {...props} className={classNames(classes.table)}>
<Datagrid rowClick="edit">
<ReferenceField source="id" reference="users" label="Name">
<FunctionField
label="Name"
render={(record) => `${record.first_name} ${record.last_name}`}
/>
</ReferenceField>
<TextField source="title"/>
<DateField source="date" />
</Datagrid>
</List>
</>
);
};
export default ExampleList;
If I had to wrap my own div that would also hold a section of a TextField, everything still works according to plan. However, this is only the case with the List, Edit, Filter, and Create, however, I'm unable to properly style the Show component.
Prior to adding any styles or wrapping some fields up in a div, this is how it would look like: Notice how the name shows up just fine.
However, when I wrap the Person Details header with the rendered name, as seen below:
<div className={detailClasses.detailSection}>
<h3 className={ detailClasses.detailSectionTitle}>Person Details</h3>
<ReferenceField
source="id"
reference="users"
label="Name"
className={detailClasses.detailSectionInfo}
>
<FunctionField
render={(record) => `${record.first_name} ${record.last_name}`}
/>
</ReferenceField>
</div>
then the information that I want rendered (in this case, the person's name), then it completely stops rendering and doesn't show up on the page.
This hasn't happened with any other react-admin component that I mentioned somewhere above.
I was wondering why this is the case, and why it is only happening with the Show component.
Thanks in advance!

Related

breakpoints not working in MUI v5 and react project

I'm trying to use breakpoints for responsive design in my page, but it dosent really seem to work. Whenever i apply any breakpoint, the whole page goes blank.
Here's my code:-
Styles.js
import { makeStyles } from "#mui/styles";
const useStyles = makeStyles((theme) => ({
title: {
display: 'none',
[theme.breakpoints.up('sm')]: {
display: 'block',
},
},
}));
export default useStyles;
Header.jsx
import React from 'react';
import { Autocomplete } from '#react-google-maps/api';
import { AppBar, Toolbar, Typography, InputBase, Box } from '#mui/material';
import SearchIcon from '#mui/icons-material/Search';
import useStyles from './styles';
const Header = () => {
const classes = useStyles();
return (
<>
<AppBar position='static'>
<Toolbar className={classes.toolbar}>
<Typography variant='h5' className={classes.title}>
Travel Advisor
</Typography>
{/* Box acts as Div */}
<Box display='flex'>
<Typography variant='h6' className={classes.title}>
Explore new places
</Typography>
{/* <Autocomplete> */}
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase placeholder='Search...' classes={{ root: classes.inputRoot, input: classes.inputInput }} />
</div>
{/* </Autocomplete> */}
</Box>
</Toolbar>
</AppBar>
</>
)
}
export default Header;
Before applying breakpoints :-
Before breakpoint
After applying breakpoints :-
After breakpoint
Make sure that you created breakpoints correctly.
https://mui.com/material-ui/customization/breakpoints/
And check if you have wrapped your app in ThemeProvider.
And I want to note that #mui/styles is deprecated. Perhaps this problem may be related to this.
https://mui.com/system/styles/basics/
⚠️ #mui/styles is the legacy styling solution for MUI. It depends on JSS as a styling solution, which is not used in the #mui/material anymore, deprecated in v5. If you don't want to have both Emotion & JSS in your bundle, please refer to the #mui/system documentation which is the recommended alternative.
⚠️ #mui/styles is not compatible with React.StrictMode or React 18.
Dont use it on newly created app.

How do i display Breadcrumb name conditionally on response from child.in React with hooks?

I am currently working on a project with React Hooks.
Parent component is a Navigator
Child component is a breadcrumb display in this navigator.
Child component fetches and displays a view with the data.
How can i use the response data in the 2. child component to set name in the 1. Child component?
My Code (omitted large portions of unnecessary code for this example):
Navigator
const { Header, Content } = Layout;
const Navigation = (props: any) => (
<>
<Layout>
<Layout>
<Header>
<Breadcrumbs
style={{ flexGrow: 2, paddingLeft: 20 }}
name='Name of User'
/>
</Header>
<Content style={{ margin: '24px 16px 0', overflow: 'hidden' }}>
<div className="content">
<Switch>
<Route exact path="/" component={MyPatients} />
<Route exact path="/Skjema" component={MySchemas} />
<Route
exact
path="/Pasient"
component={() =>
<PatientInfo
patientID={props.history.location.state}
/>
}
/>
export default withRouter(Navigation);
BreadCrumbs
import React from 'react';
import Breadcrumb from 'antd/lib/breadcrumb';
import { HomeOutlined, UserOutlined } from '#ant-design/icons';
const Breadcrumbs = (props: any) => {
return (
<>
<div className="Breadcrumbcontainer" style={props.style}>
<Breadcrumb>
<Breadcrumb.Item href="/">
<HomeOutlined />
<span style={{ color: 'black' }}>Hjem</span>
</Breadcrumb.Item>
<Breadcrumb.Item href="Pasient">
<UserOutlined />
<span style={{ color: 'black' }}>
{props.name}
</span>
</Breadcrumb.Item>
<Breadcrumb.Item>
<span>Skjema 1 - 17.04.20</span>
</Breadcrumb.Item>
</Breadcrumb>
</div>
</>
);
};
export default Breadcrumbs;
The third file contains a fetch to an api and works fine, the data in question is currently stored as response.name How can i lift this info up to Navigator?
If I understood your question correctly, there's a parent component that has two child components and you want to trigger a change from one child component in another.
You can maintain the state in the parent component, pass state in child1 and setState function in child2.
// Parent Component
const [name, setName] = useState('');
<>
<child1 name={name}/>
<child2 setName={setName}/>
</>
Try this one. I added code sandbox and you can check it out is this what you need. So from parent pass hook as props to a child, and then after the request is made inside of the child component call function from props that will fill the data inside parent component.
Update state in parent from child
I found a solution thanks to the suggestions in this thread. I made my mistake in the passing of the files to the function.
const PatientInfo = ({ patientID, setName }: any) => {
console.log(useFetch<IPatient>( // name of endpoint.... ));
const { response } = useFetch<IPatient>(
'// name of endpoint.... + patientID,
patientID,
);
This ended up fixing my problem. The problem was i initially called the two seperately, like this:
const PatientInfo = ({ patientID }: any, { setName } : any) => {
console.log(useFetch<IPatient>( // name of endpoint.... ));
const { response } = useFetch<IPatient>(
'// name of endpoint.... + patientID,
patientID,
);
So this change worked, although I am not entirely sure as to why.

Adding more than one buttons on headerRight in react-native

I am new to react-native. Here I am trying to add two buttons on headerRight. I did add one button but I could not figure out how to put more than one. Something like this.
I am using react-navigaiton and react-navigation-header-buttons.
This is how I added one button.
mainScreen
headerRight: (
<HeaderButtons HeaderButtonComponent={CustomHeaderButton}>
<Item
title={"Search"}
iconName={"md-search"}
onPress={() => {
console.log('Search')
}}
/>
</HeaderButtons>
),
CustomHeaderButton.js
import {HeaderButton, Item} from 'react-navigation-header-buttons';
import {Ionicons} from '#expo/vector-icons';
const CustomHeaderButton = props => {
return(
<HeaderButton
{...props}
IconComponent={Ionicons}
iconSize={23}
color={'black'}
/>
)
};
export default CustomHeaderButton;
You're on the right track. You should be able to simply add another Item with whatever title, icon, onPress functionality you want wrapped in the HeaderButtons component like this:
<HeaderButtons HeaderButtonComponent={CustomHeaderButton}>
<Item
title={"Search"}
iconName={"md-search"}
onPress={() => {
console.log('Search')
}}
/>
<Item
title={"Other Button"}
iconName={"other-icon-name"}
onPress={() => {
console.log('The other header icon was pressed.')
}}
/>
</HeaderButtons>
You are able to nest multiple React elements within a React element, which is what this example uses. For instance, you can nest multiple Text elements inside of a View.
It looks like you are using the react-navigation-header-buttons package, here is their example with multiple header icons for your reference as well: https://github.com/vonovak/react-navigation-header-buttons/blob/master/example/screens/UsageCustom.tsx

Routes rerender if I use a map instead of static components

I have 2 routes in my app, /validations (which is a list) and /validations/:id (which is the same list focused on a particular item).
I initially wrote my routes statically and everything works (as expected):
<Route path="/validations/:id" component={Validations} />
<Route path="/validations" component={Validations} />
However, because I wanted to do some refactoring, I put the routes in an array and used a .map to render them. But with this, when I click on an item, the whole page rerender and I lose the scroll of the list (this is a bad UX for the user because he loses where he was in the list):
const routes = [
{
path: '/validations/:id',
component: Validations,
},
{
path: '/validations',
component: Validations,
},
]
// ...and in the JSX...
{routes.map(({ path, component }) => (
<Route
key={path}
path={path}
component={component}
/>
))}
Even stranger, if I remove the key prop of the Route I get back the initial behaviour (but I have a warning by React).
Did I write something wrong? Is it a react-router bug? A React one?
How can I keep the scroll of the list with my route mapping?
Here is a reproduction: https://codesandbox.io/s/vm71x2k46l
I knew something was fishy because I've done this many times and I didn't get your results. So I noticed that you render your sidebar inside your route.
This is why it's re-rendering and setting everything to the top. Because you actually navigate to another route.
What you must do is set your Sidebar links outside the actual routes but inside the Router Component.
Like in this sandbox: https://codesandbox.io/s/p2r4pl2o3q
If you notice I changed the routes a bit:
const routes = [
{
path: "/",
component: Index
},
{
exact: true,
path: "/validations",
component: Validations
},
{
path: "/validations/:id",
component: Validations
}
];
And then created the sidebar component and set it outside the routes
<BrowserRouter>
<div>
<Sidebar />
<div style={{ marginLeft: 150 }}>{routeComponents}</div>
</div>
</BrowserRouter>
Sidebar:
var items = Array.apply(null, Array(300)).map(function(x, i) {
return i;
});
export default () => (
<div
style={{
width: 150,
height: "100vh",
display: "flex",
overflow: "auto",
position: "absolute",
flexDirection: "column"
}}
>
{items.map((item, index) => (
<Link to={`/validations/${index}`} key={index}>
Item {index}
</Link>
))}
</div>
);
Now since first click the scroll doesn't reset.
PS: Please don't mind the styling decisions I was just trying to see something work.
First you need to map the routes outside the App Component. Then you can add them mapped routes in the App in example {routeComponents}
const routeComponents = routes.map(({ path, component }, key) => <Route exact path={path} component={component} key={key} />);
const App = () => (<BrowserRouter><div>{routeComponents}</div></BrowserRouter>);
Also in the validation.js you have warning in the {items.map ...} line. I added the key prop in the link and the error gone
{items.map((item, index) => (
<Link to={`/validations/${index}`} key={index}>
Item {index}
</Link>
))}
here is the sandbox url https://codesandbox.io/s/8n2rlpmw0l

Pass data from parent component to child | React, Redux

I wonder how I can access my props item in my doorsItem component. My code in the parent is this:
const doors = this.props.doors.data.map(item => <DoorsItem item={item} />)
My DoorsItem component looked like this before:
const DoorsItem = ({ item, customer }) =>
<Grid>
<Row key={item._id}>
<Col style={{ width: '100%' }}>
<ul className="door-list">
<li className="door-flex-container">
<div className="door-flex-item-1">
<h4 className="title-text-container">
{item.address.street} // Can use 'item' here
But I wanted to connect it with redux so I ended up with this:
class DoorsItem extends Component {
render() {
return (
<Grid>
<Row>
<Col style={{ width: '100%' }}>
<ul className="door-list">
<li className="door-flex-container">
<div className="door-flex-item-1">
<h4 className="title-text-container">
{/* How can I use it here? */}
</h4>
</div>
So I was wondering what’s the best way to access the item props in my new coded component?
Thanks for reading and sorry for the nooby question!
When you're doing <DoorsItem item={item} />, you're assigning the item prop, which means that within this component you can use it like this.props.item or even better const { item } = this.props; and use the item local variable later. So for example:
const { item } = this.props;
return <span>this is the {item} you're looking for</span>
More information about that on the official documentation.
Usually, when using class based components, we should define the propTypes and defaultProps. This gives us a better understanding of the class-based component's props to use and provides validation for props to be inserted. More information here (warning: moved to a separate package since React v15.5).
Finally, you can use context, which is not the recommended way but sometimes can be helpful.

Categories