ReactDOM.render does not update containers props - reactjs

I have a container containing some html with a <div id="ID"></div>. I have a react stateful component that I want to render in that div using
React.render(<ChildComponent data={this.props.data} />, document.getElementById('ID'))
When I call an action in childcomponent and udate the redux state, the props of the parent container do not update, only the ChildComponent re-renders with old values. Those props get updated when I refresh the page.
What is the solution to this ? Is there any other way to render React component in html so that the props can be updated with new props ?

Can you share your code for <ChildComponent> and its parent? There are a number of things you might be doing wrong but the thing that stands out is that it looks like you're rendering separately from its parent instead of as a child "prop" of its parent, like so:
<ParentComponent>
<ChildComponent />
</ParentComponent>
The official docs also have a lot of examples on how to get started: https://facebook.github.io/react/docs/hello-world.html
Hope this helps!

Related

Does react re render everything when we go to a new link?

I am currently creating a react app for practice. I am curious does react render everything when we go to a new link? For eg. These are my routers
<Route exact path="/" component={AuthenticatedUser(Books)}></Route>
<Route exact path="/librarians" component={AuthenticatedUser(Librarians)}></Route>
And my Higher Order Component AuthenticatedUser is as follows:
function AuthenticatedUser(Component) {
return function AuthenticatedComponent({ ...props }) {
const classes = useStyles();
return confirmUserAuthencition() ? (
<>
<SideMenu />
<Header />
<div className={classes.appMain}>
<PageHeader></PageHeader>
<Component {...props}></Component>
</div>
</>
) : (
<Redirect to="/login" />
);
};
}
I am just curious, when I go from "/" link to "/librarians", do components SideMenu and Header rerender?
React re-renders on state change.
From: https://www.educative.io/edpresso/how-to-force-a-react-component-to-re-render
React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.
These changes can come from setState, useState, and/or forceUpdate calls
It depends on the element that redirects you to the new link. If you use react router's <Link to="/librarians"> then no, React will not re-render. However, if you use the standard html <a href="/librarians"> then it will.
No, if you're moving from / to /librarians path, your <SideMenu /> and <Header /> won't re-render. React uses virtual DOM to do the updates on actual DOM (virtual DOM is a copy of the actual DOM and it can do the updates without affecting actual DOM)
During reconcilation process, react compares virtual and actual dom and then do the updates on actual dom based on the nodes that are changed.
In your case, since you're not completely removing AuthenticatedUser component when redirection, it won't re-render <SideMenu /> and <Header /> components that are included in AuthenticatedUser component as childs. But AuthenticatedUser re-render itself since you're changing the passed Component prop.
In order identify this properly you can put a console.log in <SideMenu /> and <Header /> to check whether re-render themselves when moving from / to /librarians.
Since your HOC's return statement depends on the value of the confirmUserAuthencition(), we can't always say whether or not the and components will get re-rendered.
The DOM will stay unaffected as long as the user remains authenticated or unauthenticated. The two components need not be re-rendered each time this route is hit in this case.
React won't re-render the entire page unnecessarily. It will only re-render all components except the SideMenu and Header component.
You may find this article helpful in understanding how react re-renders - Article
It will re-render any component that has changed, as determined by shouldComponentUpdate() for each component
In your case, if you're navigating to the new page via menu navigation, it will re-render the final component, as well as the nav-menu. Depending on your implementation, it's quite likely that the it will re-render the whole AuthenticatedUser component.
Here's the component lifecycle docs:
https://reactjs.org/docs/react-component.html#shouldcomponentupdate

When Reactjs has functional component as parent and child component as class

I am new in reactjs and learning bit and pieces. I am facing an issue. The scenario is like. I have a functional component as a parent. It has a child component as a class component. I would like to set or reset the child component's state on parent's button click. Or is there any way to call the child component's any method from the parent component. I tried as
// this call from a functional component.
<PhotoPreviewUploaend setSelectedFile={setSelectedFile} ref={setImagePreviewUrl} />
Later after a button click does this:-
setImagePreviewUrl('');
I read ref attribute allows access to the component. I tried this ref between 2 class component both parent and child is class components and it works as expected. But when did the same from a functional component it has no effect at all. How can I do it?
You are not embracing react one-way data flow by using refs like that; it might not behave the way you expect;
You should pass parent state handler logic function to the child component,
then child component call it with proper value; as the result your parent state will be updated and you have nice and clean one way data flow; you can use this in any kind of component, since you don't mess with this bindings in functional components;
This example demonstrates it in action:
function App() {
// Define your state
const [someState, setSomeState] = useState(0);
return (
<div className="container">
<Child parentCallback={setSomeState} />
</div>
);
}
class Child extends Component {
render(){
return(
<div>
<button
onClick={() => this.props.parentCallback(/*someValue*/)}
>
click me!
</button>
</div>
)
}
}

How to get react grand-child node to render when child is out of my control

I have a react component which uses a 3rd party library Component as a Child node. The Grand children (or the children of the 3rd party libary) are under my control. When my component receives new props it re-renders, however the 3rd party component seems to stop my components grand-children from re-rendering also, even though the props my component received, are passed to the non-re-rendering components directly
If I remove the 3rd party component then my component re-renders as do the grand-children.
render() {
<div>
<ThirdPartyComponent props={blah}>
{this.props.products.map(prod => <MyGrandChildrenComponents product={prod} />
</ThirdPartyComponent>
</div>
}
A concrete example can be found on this code sandbox: codesandbox.io/s/silly-grass-7frlx
I'd expect my MyGrandChildrenComponents component to get updated when this.props.products changes... Any hints?
This can happen if ThirdPartyComponent is a stateful component and is not handling its prop updates correctly. One way to force a re-render is to add a key prop to your ThirdPartyComponent and update its value when a re-render is needed.
render() {
<div>
<ThirdPartyComponent key={something-that-changes-when-rerender-needed} props={blah}>
{this.props.products.map(prod => <MyGrandChildrenComponents product={prod} />
</ThirdPartyComponent>
</div>
}
If ThirdPartyComponent is a PureComponent it should re render (and so re render its children) when one of its props changes so you can try:
render() {
<div>
<ThirdPartyComponent props={blah} products={this.props.products}>
{this.props.products.map(prod => <MyGrandChildrenComponents product={prod} />
</ThirdPartyComponent>
</div>
}
To trigger re renders when this.props.products changes.
But any prop should do.
If ThirdPartyComponent has a custom implementation of shouldComponentUpdate, then you will have to find the specific prop which triggers update if it exists.

React re-renders component unnecessary after prop change

So I have reducer autocomplete that stores all options loaded throught react-select. I also have two components - <Parent /> and <Modal />. Both of them are connected to redux state to receive autocomplete props, because both of them have its own <AsyncSelect /> component.
Select that is children of <Parent /> component, receives options from reducer: autocomplete.labels. Second Select component that is children of <Modal />, receives options from reducer: autocomplete.differentLabels.
Now, when I'm using Select that is children of Modal, whole Parent component is re-rendered, even if there is no jsx dependent on autocomplete. Is this expected behavior? Because of this re-rendering, performance decreases.
Maybe should I divide labels and differentLabels into separate reducers?
A possible solution can be to use the shouldComponentUpdate to compare the current props to previous props and do some logic there to prevent unnecessary update.
shouldComponentUpdate(nextProps, nextState) {
if (this.props.myProp !== nextProps.myProp) {
// Your logic
return false;
}
return true;
}

What is causing my component to unmount?

I'm making an app where I have an Overlay component and a Map component rendering behind it just like this:
<div>
{showOverlay && <Overlay />}
<Map /> // this component should mount once
</div>
The overlay is shown to let the map load underneath but when I remove the Overlay (set showOverlay to false here) the Map component re-load.
At first I thought the Map component was just re-rendering, but after some digging I discovered that the component was actually re-mounting.
If I log in the componentWillMount, componentWillUnmount and render methods, the log appear in that order (which seems contradictory)
render
willUnmount
willMount
The parent does not re-mount, only the Map component do.
The Map component just render a div that reference a mapbox-gl-js map (like this https://gist.github.com/tristen/5c4b346ae38892f732504e6785d87057#file-map-js)
What can cause my component to re-mount itself like that ?
Thanks !

Resources