I'm trying to pass props for width from a parent component to a child JS file, but cannot seem to get the props value in the child JS file. The parent is the following:
import React from 'react';
import Child from './Child';
export default class Home extends React.Component {
state = {
width: 1000
}
render(){
return(
<div>
<Child width={this.width} />
</div>
);
}
}
The separate child JS file is the following:
import React from 'react';
const svgWidth = 650, // Load prop here
svgHeight = 340;
What I've tried is the following but is not working for me:
import React from 'react';
const Child = (props) => {
console.log({props.width}); // Getting an error that ',' is expected
return {props.width};
}
Can someone please help me with passing the width value from ?
Change to the following, as you should access state through this.state, like so:
<Child width={this.state.width} />
Either use the prop drilling, hence pass the values from parent to child as a prop.
But exact answer to your question will be :
create a blank object in separate js file and export it and then in componentDidMount populate that object with the props which you want to save. Next time when ever you will use that object anywhere in normal js file you will get the props.
If you intend to pass props to a child component, then I would start with the following:
import React from 'react';
import Child from './Child';
export default class Home extends React.Component {
constructor(props) { // don't forget to add a constructor
super(props); // also required
this.state = {
width: 1000
}
}
render(){
// to pass state use {this.state}
return(
<div>
<Child width={this.state.width} />
</div>
);
}
}
However, if that is not the case and instead you want to export state to a separate js file (that may not even be a React component), then you may have to look at export syntax. I am struggling with a similar problem right now and I already tried what Vikash Kumar suggested without success. This is explained on this question but I was not successful with that approach either: export function inside react component or access state in same file outside of component
Related
I'm learning React and I have a problem trying to read my props in a child component.
The child component is:
const HelloWorldApp = ( props ) => {
console.log(props);
return (<>
<h2> {props} </h2>
</>
);
}
export default HelloWorldApp;
The parent is:
import React from 'react';
import {createRoot} from 'react-dom/client';
import HelloWorldApp from './FirstApp';
import { SecondApp } from './SecondApp';
import './styles.css';
createRoot(document.getElementById('root')).render(HelloWorldApp());
createRoot(document.getElementById('raiz')).render(SecondApp());
1) What is the problem?
2) How can I pass props from the parent to the children component?
I think the problem is in the render function. You need something like this:
createRoot(document.getElementById('root'))
.render(<HelloWorldApp />);
In react , you don't need to render all the components in separate CreateRoot..
render your child component with props inside the parent component
The parent Component
import React from 'react';
import {createRoot} from 'react-dom/client';
import HelloWorldApp from './FirstApp';
import './styles.css';
createRoot(document.getElementById('root')).render(<HelloWorldApp data="propsData" />);
The child Component
const HelloWorldApp = ( props ) => {
console.log(props);
// {data: "dummyData"}
return (<>
// you can't able to render object inside the jsx
<h2> {props.data} </h2>
</>
);
}
export default HelloWorldApp;
The structure React program is on constantly changing over the time, whereby i recommend you use command npm create-react-app to have the latest standards of programming in that framework.
Only one createRoot is necessary in React renderize DOM, and i recommend you receive parameters with destructuring in child component, the parameters must been passed in JSX tags as attributes
There's a familiar gotcha when testing React components that are connected to Redux in Enzyme. You may have run into this error:
Invariant Violation: Could not find "store" in either the context or props of "Connect(YourComponent)
This is resolved by exporting the component under test twice:
export class YourComponent extends Component {}
export default connect(mapStateToProps, mapDispatchToProps)(YourComponent);
And in your test import YourComponent as an object:
import { YourComponent } from '../pathToYourComponent'
I've run into a novel scenario regarding this issue.
I'm testing a connected component, and I'm using the solution above to resolve that issue, however inside that component there is another connected component that gets rendered when certain props are present.
import React, { Component } from 'react';
export class YourComponent extends Component {
constructor(props) {
super(props)
}
render() {
const { arrayOfObjects } = this.props;
let nestedConnectedComponent;
if (arrayOfObjects.length) {
nestedConnectedComponent = arrayOfObjects.map((ele, idx) => (
<NestedConnectedComponent
key={idx}
/>
))
}
return (
<div> {arrayOfObjects} </div>
)
}
}
function mapStateToProps(){}
function mapDispatchToProps(){}
export default connect(mapStateToProps, mapDispatchToProps)(YourComponent);
How do you avoid the "could not find store" error when you are testing a component that contains a component that is connected to redux?
The component is being shallow rendered in the latest version of Enzyme.
You won't get this error if you use shallow rendering, from docs
'Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren't indirectly asserting on behavior of child components.'
I have started learning basic of Context API in ReactJS.
This is a part of reactJS code which uses reactJS.
app.js
import React from 'react';
import ReactDOM from 'react-dom';
import LeftPane from './LeftPane';
import RightPane from './RightPane';
import {SampleProvider} from './sample';
const App =()=>{
return(
<SampleProvider>
<div className="panes">
<LeftPane/>
<RightPane/>
</div>
</SampleProvider>
)
}
export default App;
ReactDOM.render(
<App/>,
document.getElementById('root')
)
RightPane.js
RightPane.js
import React from 'react';
import Receives from './Receives';
const RightPane =()=>{
return(
<div className="pane">
<Receives/>
</div>
)
};
export default RightPane;
sample.js
import React,{Component , createContext} from 'react';
const Context = createContext();
const {Provider, Consumer : SampleConsumer}=Context;
class SampleProvider extends Component{
state={
value:'default value'
}
actions={
setValue:(value)=>{
this.setState({value});
}
}
render(){
const {state,actions}=this;
const value={state,actions};
return(
<Provider value={value}>
{this.props.children}
</Provider>
)
}
}
export{
SampleProvider,
SampleConsumer
};
Receives.js
import React from 'react';
import {SampleConsumer} from './sample';
const Receives = ()=>{
return(
<SampleConsumer>
{
(sample)=>(
<div>
Value:{sample.state.value}
</div>
)
}
</SampleConsumer>
)
}
console.log(Receives);
export default Receives;
Everything is fine. I understand everything except the function in SampleConsumer
component.
function in SampleConsumer uses sample as parameter.
I tested and sample.state.value renders 'default value' and it is the value of the state which is declared in SampleProvider component.
SampleProvider passes down the state as props to Provider component. I understand
Provider can use that state. But how the parameter in SampleConsumer understands
state in SampleProvider component? I have never passed the state as props to
SampleProvider component ..(I understood so. Maybe it's wrong)
I read this documentation
https://reactjs.org/docs/context.html
but didn't understand 100%
Everything is fine. I understand everything except the function in SampleConsumer component.
You have set SampleConsumer to point to the raw Consumer output of createContext(). It will function exactly the same as the ThemeContext.Consumer example in the docs.
function in SampleConsumer uses sample as parameter. I tested and sample.state.value renders 'default value' and it is the value of the state which is declared in SampleProvider component.
You have wrapped the raw Provider output of createContext() with your SampleProvider component. As you did so, you set the Provider's context value to (initially) be:
{
state: {
value: 'default value'
},
actions: {
setValue: (value) => { this.setState({value}) }
}
}
Meaning that whenever you invoke SampleConsumer that is a child of SampleProvider, the argument in the "child as a function" will be passed that value. In other words, this would display the string representation of the object in the above snippet:
<SampleConsumer>
{ (value) => <div>{value.toString()}</div> }
</SampleConsumer>
SampleProvider passes down the state as props to Provider component. I understand Provider can use that state.
Correct - you have set Provider's value prop to be equal to an object that contains SampleProvider's state.
But how the parameter in SampleConsumer understands state in SampleProvider component?
This is exactly what the context API accomplishes. SampleConsumer has access to Provider's value prop, without needing to pass the prop through all the child elements in between. Note that your code here doesn't have anything in between, so it's a little trivial; the docs you linked provide a better example.
I have never passed the state as props to SampleProvider component ..(I understood so. Maybe it's wrong)
You passed SampleProvider's state as a prop to Provider. Provider, in turn, passed its prop down to SampleConsumer.
I think the core of the misunderstanding here is your use (or naming) of SampleProvider. I'm not sure what you're trying to do with that state, but it's not really a "Provider" anymore and makes things confusing. This is unlike your SampleConsumer, which is still the default Consumer, just renamed.
I have the following react component:
class Cmp extends React.Component {
render () {
return <h3>{this.props.title}</h3>;
}
}
But I would like to expose or say to the consumer of my component to use it with a title otherwise it does not work the component.
Consumer would use it like
<Cmp title='Some fancy title' />
I need the consumer of my component to know that he should provide a title otherwise the component does not have any sense.
You can use PropTypes and set it to isRequired. You can also check if the prop is set at componentWillReceiveProps() and throw your error.
If you return null from a render method, nothing is rendered. You could use this knowledge to conditionally check if the prop is passed, and return null if the prop is not passed. The advantage here over using componentWillReceiveProps() is that you could use a functional component rather than a class component.
In rare cases you might want a component to hide itself even though it
was rendered by another component. To do this return null instead of
its render output.
Preventing Component from Rendering
Realistically you would also use PropTypes.
Cmp.propTypes = {
title: PropTypes.string.isRequired
};
Short Example
import React from 'react';
import PropTypes from 'prop-types';
const Cmp = (props) => props.title ? <h3>{props.title}</h3> : null
Cmp.propTypes = {
title: PropTypes.string.isRequired
}
export default Cmp;
I am stuck. I have several seperate components on seperate files. If I render them in main.jsx like following:
ReactDOM.render(<LandingPageBox/>, document.getElementById("page-landing"));
ReactDOM.render(<TopPlayerBox topPlayersData={topPlayersData}/>, document.getElementById("wrapper profile-data-wrapper"));
ReactDOM.render(<RecentGamesBox recentGamesData={recentGamesData}/>, document.getElementById("history wrapper"));
Everything works fine, but I wonder if it is a good practice? Maybe it is possible to do something like there would be only one ReactDom.render like:
ReactDOM.render(<LandingPageBox recentGamesData={recentGamesData} topPlayersData={topPlayersData}/>, document.getElementById("page-landing"));
I tried different kinds of variatons of LandingPageBox to somehow include those other two components, but had no luck. They sometimes rendered outside the page and so on. I thought it should look something like this:
import React from 'react';
import RecentGames from '../RecentGames/RecentGames.jsx';
import TopPlayers from '../TopPlayers/TopPlayers.jsx';
import PageTop from './PageTop.jsx';
import PageBottom from './PageBottom.jsx';
class LandingPageBox extends React.Component {
render() {
return (
<body className="page-landing">
<PageTop>
<TopPlayers topPlayersData={this.props.topPlayersData} />
</PageTop>
<PageBottom>
<RecentGames recentGamesData= {this.props.recentGamesData}/>
</PageBottom>
</body>
);
}
}
export default LandingPageBox;
But this code only renders PageTop and PageBottom, without player or game components.
So my question would be, how to set up LandingPageBox file so that TopPlayers component would render inside PageTop component and RecentGames component would render inside PageBottom component? Thank you.
In your example
return (
<body className="page-landing">
<PageTop>
<TopPlayers topPlayersData={this.props.topPlayersData} />
</PageTop>
<PageBottom>
<RecentGames recentGamesData= {this.props.recentGamesData}/>
</PageBottom>
</body>
);
React will only render the top-level custom components PageTop and PageBottom, as you already found out. The other components (TopPlayers and RecentGames) are nested within those components. What does that mean? React does not just display those nested components because it would not know how to do this. Instead, all rendering must be done by the outer components PageTop and PageBottom. React just passes the nested components to them (PageTop gets TopPlayers, PageBottom gets RecentGames) in this.props.children. Now it is up to the outer components what to do with these nested components. In your example, you would modify the PageTop and PageBottom components to use {this.props.children} to display their nested components in a suitable way.
You are right. You can use as many nested components as you want. It's one of the main concepts in react.
You can access them in this.props.children.
Do it like this:
var Parent = React.createClass({
render: function() {
return <div>{this.props.children}</div>;
}
});
ReactDOM.render(
<Parent>
<Child/>
<Child/>
</Parent>,
node
);
Read more here - https://facebook.github.io/react/docs/multiple-components.html
And here - http://buildwithreact.com/article/component-children
Here Car component is inside the another component i.e Garage components.
When Garage component in rendering Car component is also renders.
Same concept as like one function inside another function.
class Car extends React.Component {
render() {
return <h2>I am a Car!</h2>;
}
}
class Garage extends React.Component {
render() {
return (
<div>
<h1>Who lives in my Garage?</h1>
<Car />
</div>
);
}
}
ReactDOM.render(<Garage />, document.getElementById('root'));