Disabling unfocused scenes in react-native-router-flux - reactjs

I am using redux to change style of my custom NavBar component. My NavBar is not part of Router neither scenes, I introduce them in direct scene JSX. Example JSX from my scene component:
<View style={{ flex: 1 }}>
<NavigationBar /> <--- My custom NavBar
{ this.renderScreen() }
<Tabulator
tabs={TABS}
style={styles.navbar}
listenTo='screen'
/>
</View>
In the second scene I have a ScrollView which is dispatching actions when I scroll the view. For an example, I am dispatching opacity of the NavBar while you scroll down and change its title after a certain y value. The problem is, when I scroll the view and before it can stop I go back from the second scene to the first one, the ScrollView did not yet stopped scrolling so it dispatches few more actions.
Is there a way to disable the scene?
I have noticed that this gets called while the scene is alive during the scene change animation until componentWillUnmount() gets called.
I tried to put a reducer into the router and dispatching an action that the scene switching is in progress. I check if the action type is anything else than REACT_NATIVE_ROUTER_FLUX_FOCUS then the changing is in progress. so while it is true the action changing the NavBar is ignored, but this sets false before it gets to unmounting.

Related

Storybook - Animation works on Canvas tab but not in Doc tab

I'm writing documentation for a React 18 component with storybook, a simple progress bar.
It's awesome, but i'm stumbling upon a annoying problem.
My component works very well in my application, and in the storybook canvas tab too.
But, inside the storybook Doc tab, it seems that it gets rerendered every time i change a prop in the defined below it.
Here's my documentation (mdx) file:
import { ArgsTable, Canvas, Meta, Story } from "#storybook/addon-docs/blocks";
import { ProgressBar } from "./ProgressBar";
<Meta
title="Layout/Header/ProgressBar"
component={ProgressBar}
/>
# ProgressBar
A progress bar for the Header component.
## Props
export const Template = (args) => <ProgressBar {...args} />;
<Canvas>
<Story
name="ProgressBar"
args={{
step: 2,
totalSteps: 12,
}}
>
{Template.bind({})}
</Story>
</Canvas>
<ArgsTable story="ProgressBar" />
The component is displayed properly but, incrementing the step prop in the argsTable, the progress bar is not animating because it gets rerendered completely (tested adding the useEffect hook with [] as dependency).
I think is related to how storybook handle the documentation, because i don't have this problem in the canvas tab or in an app where i use the same ProgressBar component

How to force one react component to not re-render?

I have a main react component (The entire page) that contains several other UI items in it. One of those UI items is an OpenLayers map. Another component is a text field that contains the latitude and longitude of the current mouse pointer position.
I want the text field to update whenever the mouse pointer moves on the map. In my code's current state, this works.
The problem is every time the mouse moves and I update the react state value for the latitude/longitude (which gets rendered in the text field as expected) the map re-renders. This looks terrible because the map flashes every time as it begins to load the map tiles.
So I have the mouse latitude/longitude position, but I can't get the map to not flash/stutter/strobe.
Is there a way to get a mouse event from the map component, and send it to another component on the same screen without causing the render method to redraw the map every time? Or is React the wrong tool for this project?
As a note, I'm using React Redux to handle some state values, such as the map object. All of my child components are React functional components, but the main component for the page is a React class component.
If it helps, I set the mouse listener on the map like this:
this.props.map.on('pointermove', event => {
this.setState({
mouseCoordinates: (event.coordinate),
});
});
This is my render method:
render() {
return (
<div className="main">
<p className={noMargPad}>
{this.state.mouseCoordinates}
</p>
<Map
center={fromLonLat(this.state.center)}
zoom={this.state.zoom}
>
<Layers>
<TileLayer source={osm()} zIndex={0} />
{this.state.showLayer1 && (
<VectorLayer
source={vector({
features: new GeoJSON().readFeatures(geojsonObject, {
featureProjection: get("EPSG:3857"),
}),
})}
style={FeatureStyles.MultiPolygon}
/>
)}
{this.state.showMarker && (
<VectorLayer source={vector({
features: this.state.features
})} />
)}
</Layers>
<Controls>
<FullScreenControl />
</Controls>
</Map>
</div>
);
}
One of the main advantages of using a tool like React is it will only refresh the components in the render method that have had an update to their dependent data. See this article for more information.
The fact that your map is rendering again indicates that the map, or one of its children is being passed a piece of data that keeps changing.
Based on your code, one possibility is the call to OSM(), since that's a constructor from the OpenLayers API. A new object/class instance in JavaScript could cause data re-render.

React pass onMouseHover to Children component

I am implementing a small react component called react-hover in it's V2 version.
This lib just simply enable user to define their trigger and hover component and make the hover component appear when mouse hover on trigger component.
<ReactHover
options={optionsCursorTrueWithMargin}>
<ReactHover.Trigger>
<TriggerComponent />
</ReactHover.Trigger>
<ReactHover.Hover>
<HoverComponent />
</ReactHover.Hover>
</ReactHover>
Now I am facing an issue of passing the onMouseHover events to the children component in tigger component:
render () {
return (
<div
onMouseOver={this.onMouseOver.bind(this)}
onMouseOut={this.onMouseOut.bind(this)}
onMouseMove={this.onMouseMove.bind(this)}
onTouchStart={this.onTouchStart.bind(this)}
onTouchEnd={this.onTouchEnd.bind(this)}
>
{this.props.children.props.children}
</div>
)
}
Because only the children component can tigger the hover component, but in above implementation, it is binding the listeners to the parent div, so I met the issue that parent div's css width is more than the childen's width, so when mouse is on the div ( not in the children) the hover component show up. But I cannot control the children component's inner code as it is passed in as children.
I am just wondering how to tackle this issue?
The example code is here.
The place where bind the mouse event is here
Just wondering what's the solution for this?
how to bind those events to the children component when cannot put code in children component.
Below is showing when mouse outside of trigger component still can trigger the hover component.
Just resolved by add ref to the container and retrieve Children's width:
let childStyles = this.refs.triggerContainer.children[0].style
and apply to the current parent container.
check this code

How to reload the component life cycle when reusing component in react-natvie?

Suppose the app have a menu lists on the left, every menu reuses same content component on the right.(I use react-redux)
If I click the menu, the menu state update and the content component will load different data and do some other actions. But after the first load the content component will not execute componentWillMount, componentDidMount,it only has componentWillReceiveProps...etc. It is complex to handle the similar state. I hope the component will reload every time so that I can handle the state in componentDidMount. Is it about Class and Instance ? I hope get some good advice.
I have solved previous problem,but there is a bug about RefreshControl of ScrollView or ListView. Next is the code of content component:
<View style={{flex: 1}}>
<ListView
<RefreshControl
refreshing = {tableFetching || refreshTable}
onRefresh = {this._onRefresh}
tintColor = "gray"
title = "loading..." />
enableEmptySections = {true}
dataSource={ds.cloneWithRows(tableData)}
renderRow={this.renderRow}
style={{flex: 1}} />
</View>
When the component load firstly, the RefreshControl shows normally. But when I change the menu, the component update and load the new datas, the RefreshControl indicator doesn't show , it scroll to the above not to see.
What I see is that you are not able to manage the state. First of all componentWillMount and componentDidMount will work only for the first time until you don't move it out from the navigator stack(popRoute). In your case you don't want to pop the route to manage state so you can use other lifecycle components such as componentWillRecieveProps(),shouldComponentUpdate() etc. I have one more rescue plan for you, the forceUpdate() function which will update the component forcefully, but usage of it is prohibited until and unless there is no otherway.
Cheers:)

Avoid `OverlayTrigger` from unmounting overlay

How do I stop the OverlayTrigger component from react-bootstrap from unmounting its overlay component when the onHide prop is called? This is the component that shows the Popover. It is not an issue with Popover since setting overlay={<ComplexComponent />} causes the same issue where ComplexComponent is mounted every time the OverlayTrigger is triggered.
This is a simplified version of what I'm attempting:
const overlay = (<Popover id="some-random-id">
<ComplexComponent />
</Popover>;
<OverlayTrigger
trigger={['hover', 'focus']}
placement="top"
overlay={overlay}
>
<span>trigger label</span>
</OverlayTrigger>
The reason I need to just hide the overlay instead of unmounting it is that ComplexComponent makes service calls on componentWillMount and takes a considerable amount of time to do that initial fetch. I've considered using refs but haven't come up with a good enough strategy.

Resources