Pass data from parent component to child | React, Redux - javascript

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.

Related

Passing child state to parent in React //

I'm looking to pass my state back up from a child component to parent. And yes I know there is similar online! however this is specifically with the formkit component, and I cannot resolve it.
I have a parent component, which contains a FrameworkList, this is an iterable dropdown which creates an array.
Please see parent:
<MainContainerWrapper>
<AccordionContainer>
<FrameworkList ref={parent}/>
</AccordionContainer>
</MainContainerWrapper>
And with this, I have a child component. This component has an array called items. When items is changed the state is updated and the array is modified. My goal is to have this array based to parent component so I can complete some Redux dispatch events on an onSubmit. However, if there's a better way to do this in the child component, let me know.
Child:
export default forwardRef(function list(props, ref) {
THIS IS THE STATE, items, TO BE PASSED UP.
const [items, item, addItem, input, sortUp, sortDown, sortList, remove] =
UseListFunctions([
{ id: 0, name: 'Transparency' },
{ id: 1, name: 'Collaboration' },
{ id: 2, name: 'Flexible working arrangements' },
]);
// console.log(items)
return (
<StageComponent data-has-animation={ref ? true : null}>
<div className="logo">
{(!ref && (
<img
src="https://cdn.formk.it/web-assets/logo-auto-animate.svg"
width="300"
height="37"
/>
)) ||
''}
</div>
<ULComponent ref={ref}>
{items.map((item) => (
<ListComponent key={item.id}>
{/* text is here */}
{/* <span>{item.name}</span> */}
<Typography variant="subtitle1" color="black">
{item.name}
</Typography>
<div className="action-icons">
<button onClick={() => sortUp(item)}>
<Arrow direction="up" />
</button>
<button onClick={() => sortDown(item)}>
<Arrow direction="down" />
</button>
<button className="remove" onClick={() => remove(item)}>
<Close />
</button>
</div>
</ListComponent>
))}
<ListComponent>
I hope this is relatively well explained. If anyone knows how to pass this array back up, it would be a life saver.
Alternatively, if someone knows how to utilise redux directly in this child component, that would also help. I don't believe I can use the redux dispatch in this component directly.
I encourage you to lift the child's state to the parent component and pass that state down to the child component(s).

Issue with React Component

I am new to React, and am trying to call a function which acts as a component, but returns two values, one called 'render' which just returns a component wrapped in a div, and another called sliderVal, which is an internal state value of that slider. Below is code from MySlider.js
function MySlider(props) {
const [sliderVal, setSliderVal] = useState(1);
return{
render:(
<div>
<Grid container justify = "center">
<Box sx={{ width: 250 }}>
<Typography id="input-slider" gutterBottom>
{props}
</Typography>
<Slider
defaultValue={1}
valueLabelDisplay="auto"
step={1}
value={sliderVal}
marks
min={1}
max={10}
onChange={(_, newValue) => setSliderVal(newValue)}
/>
</Box>
</Grid>
</div>
),
sliderVal
}
In my App.js, I am using the following code to render two sliders, and pass their values into another component.
var {render, sliderVal} = MySlider("Number of Paragraphs");
var {render1, sliderVal1} = MySlider("Number of Words");
The first one works just fine, I can use {render} to render the slider, and {sliderVal} to access its value and pass into another component. However the 2nd one does not work and nothing renders. When I console.log render1 and sliderVal1, they are both undefined. Any insight is greatly appreciated!
The 2nd change to:
var {render:render1, sliderVal:sliderVal1} = MySlider("Number of Words");

How to use a state from another file in react

I have a storybook project and created a new custom component. I used a hover state and when I hover the component, it updates its className and it just works fine. Named: ProductSize
And then, I created a new component to group the ProductSize component and named it as ProductSizeGroup and grouped them by the Json inside the ProductSizeGroup stories.
And here is the final product screen:
Here, I want to see the sizes when I hover the boxes. But, it shows me all the sizes all alone like this. Apparently, I only want to see XSmall when I hover to XS, Small in S etc..:
Edit: Many people asked for the coding side and that is here - a live coding example:
https://codesandbox.io/s/usestateissue-10l4l
So, how to solve it?
Here is the ProductSizeGroup component code displaying the ProductSize items and hover-triggered sizes
const ProductSizeGroup: React.FC<IProductSizeGroupProps> = (props) => {
const { ProductSizes } = props;
const [inHover, setHover] = useState(false);
return (
<Box style={{ width: "100%" }}>
<Typography>
{" "}
Size:
{ProductSizes.map((products: any) =>
inHover ? products.name : undefined
)}
</Typography>
<Box display="flex" justifyContent="flex-start" p={1} m={1}>
{ProductSizes.map((products: any) => (
<Box
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
<ProductSize
inStock={products.inStock}
sizeText={products.sizeText}
name={products.name}
/>
</Box>
))}
</Box>
</Box>
);
};
The issue is that you're displaying the size via the following
Size:
{ProductSizes.map((products: any) =>
inHover ? products.name : undefined
)}
where inHover is simply a Boolean value. So this will either show all name values or nothing.
I think what would work better is something like the following where you set the hovered state to the value you want and simply display it
const [hovered, setHovered] = useState<string | undefined>();
return (
<!-- snip -->
<Typography>Size: {hovered}</Typography>
<!-- snip -->
{ProductSizes.map(product => (
<Box
onMouseEnter={() => setHovered(product.name)}
onMouseLeave={() => setHovered(undefined)}
>
<!-- etc -->
</Box>
))}
)
Take note that I've also removed some of your any typings in the sandbox.
In order to handle states, you can use the react context provider: https://reactjs.org/docs/context.html or react redux https://react-redux.js.org/.
Depending on how many states you have and what you want to do with them you can choose one of the two. React-redux loads only the states you need, it is faster, but it has a specific structure that you need to follow. It is more complex at the beginning, but you can easier handle multiple states.
Context provider is already installed with react, it is easier to set up, but it is slower since it loads all states on each page load.

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

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!

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.

Categories