'My React component does not update in the Safari browser
Thought everything was going great. Works perfectly in Chrome, FF, Edge, even IE 11!
The parent component holds all the sate. I pass the bets object to the child component which calculates a count to pass to the grandchild component to display.
The parent state 'bets' is an object with the keys as an ID and the value as an object.
The parent state is correctly changing when I interact with the app. Why will only Safari not update when the parent state changes? (on iOS and MacOS)
Parent
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
bets: {}
};
}
}
Child
getBadgeCount = (league) => {
const bets = this.props.bets;
let count = 0;
Object.keys(bets).map((bet) => bets[bet].event.league === league && count++);
return count;
};
// ...
<ChildItem count={this.getBadgeCount(league)} />
GrandChild
class GrandChildComponent extends React.Component {
render() {
const { count } = this.props;
return (
<div>
<div>
{count > 0 && <div>{count}</div>}
</div>
</div>
);
}
}
I console.log the count inside the grandchild render and in the componentDidUpdate and it shows the right number. Is there something apple/safari specific with react I am missing?
Solution 1:[1]
In the case where there are variables being changed based on which you can switch between the styles (opacity: 1 or opacity: 0.99) You can try adding a key to the element which is not being updated in Safari/iOS.
<div key={new Date()} className={'myComponent'}>{Count}</div>
I ran into the same problem, this seems to work for now.
Solution 2:[2]
I just run into similar problem. Safari didn't re-render some texts implemented as:
<span>{someValue}</span>
On 'someValue' field update, reactJS worked fine (element was requested to render) but Safari re-renders only area of new value (shorter than previous). UI glitches :-/
If I done anything to CSS via Developer tools, element has been rendered again and looks fine :-/
After some tries, I luckily used a 'display: block;' style property and it starts to re-rendering absolutely fine. Also 'display: inline-block;' will fix that problem too, if it is needed to be used.
Solution 3:[3]
I had a similar problem where a center positioned span using flexbox inside a div wasn't updating correctly in Safari.
Restyling this div to use display:block solved this rendering issue so this might be worth looking into if anyone runs into the same problem in the future.
P.S. Looking at the styling code now, making the change was actually a much cleaner solution as it reduced the amount of lines from 4 to 1 but this might not be the case for all scenarios of course.
before:
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
after: (is a div so display:block is already used)
text-align: center;
Solution 4:[4]
When using map function , React looks at the keys :
To identify which items have changed, are added, or are removed.
Solution :
- Now, As you use map function u must Add Key to the div inside map .
- Use a key variable that is connected to the logic behind clicking , so that when clicking the key , the variable is updated and so React will rerender this grandchild div .
As the following code :
<div key={Count} className={'myComponent'}>{Count}</div>
PS : I discourage to use Date as a key , because I f u are clicking quickly it glitches , while if u are connecting it with a state with the logic behind clicking , it won't .
Solution 5:[5]
this may help you:
will-change: transform;
Solution 6:[6]
I know it may be late but what helped me with Safari not re-rendering reused components was:
will-change: opacity;
You may have to experiment which element in your HTML hierarchy to apply this to. It makes no sense because no opacity was being changed in my case but it did fix the problem. Thank you, Apple...
Solution 7:[7]
We also ran into this problem. So, I did a short research about it and got the gist as follows:
It works by providing the unique key to the element(key={new Date()} works bcz unique even with seconds) which is not rerendering properly say a description as text inside it that changes by button or an event.
So what I got as a gist basically, providing the individual key make new dom element to react during reconcilation process rather than changing same value inside the element so basically that element showing object is made unique instead of changing value inside that dom element so I think safari specific it is as it is holding state of the element rendering dynamically. So after providing the key prop you are basically rendering the unique different element(obviously with different text/object inside it). This basically utilizes here the concept of keys while we render a list in react component.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Shivang Bhandari |
| Solution 2 | zegee29 |
| Solution 3 | Jonathan Lauwers |
| Solution 4 | rawand deheliah |
| Solution 5 | Lukianchuk Maxim |
| Solution 6 | David Kartoffelkopf |
| Solution 7 |
