Rendering lists react native - javascript

I'm using react native and have parent component with modal. When modal opens, my child component with list rerenders one time, but interface freezing for ~1 or 2 seconds depends on elements in the list. Average size of list is 50 elements. What can be a problem?
<View style={styles.screenWrapper}>
<View style={styles.container}>
<List
onChoose={onChoose}
flightOffers={paginatedFlightOffers}
isRequesting={isLoadingOffers}
isLoadingMore={isLoadMore}
isLoadingResults={!paginatedFlightOffers.length}
currency={{ value: searchId?.searchId.currencyRates[body.currency], name: body.currency }}
showMoreFlightOffers={showMoreFlightOffers}
/>
</View>
<NativeModal
visible={isDetails}
onClose={onDetailsClose}
animationType="fade"
>
<View>
<Text>asdf</Text>
</View>
</NativeModal>
</View>
Insinde the List component there is FlatList and sometimes it writes attention message with advice that I used. Maybe it is possible to avoid rerendering because props in List component remains the same. I have tried to use React.memo, but still rerendering exists

You should try using flat list as it virtualize list it renders only small batches of elements and more efficient

Got answer to this question from my friend and fixed rerendering. The reason List was rerendering everytime when modal was opened is that isDetails state was changing in the parent component. So everytime state changed my parent component was also fully rerendered.
To fix it I created isDetail state in recoil(you can to it throw redux, mobx, context etc.), created new component with modal and in this new component called isDetail from recoil.

Related

How do you render an array of components in a way that preserves the child component state?

Basically, I have one page that consists of three main components. A map, a custom Search box, and a list that shows the selected locations, which is stored in the main component's state. For each location it renders a component (MarkerList) that has its own state and interactivity. These components are created using a .map() function.
The problem arises when a user interacts with the other two components. Any update to the main component's state causes it to create a new array of List components, and thus resets the state of that component. From my understanding this is what .map is supposed to do.
I've tried wrapping the .map in a callback, and that works until the itemList is updated, and then all interactivity with any of the list components is reset because all the components are new. I've also tried to instead render an array of the components instead of using the .map() function to no avail.
return (
<div>
<TestMap />
<div>
<Search items={items} />
{itemList.map(i =>
<MarkerList key={uuid()} items={i.items}/>
)}
</div>
</div>
)
I've omitted a lot of the styling and props. But the TestMap and Search components but have props which allow them to alter this component's state.
Is there any way to go about rendering the MarkerList components in such a way that they are not destroyed/created on every state change? And would there be any way to "remember" the state for each MarkerList when a new item is added to the itemList?
Any help would be greatly appreciated!

ReactJS passing input data to next screen/component

I've looked up whole google for my answer (haha).
What I am trying to achieve:
My fist screen is a form with some input fields which store the input to state.
By clicking "submit" the user comes to the next page/screen, where the previous input is supposed to show up. I want to show only the input data as a p-tag, not as an input tag anymore.
How do I achieve this? I am bloody new to reactjs.
I've thought about multiple solutions:
store the input data to an external JSON (which seems pretty complicated)
pass the data as props, but I am not aware of how I would do this
Thanks so far!
I'm going to assume that your second screen has the same parent component as your first, something like this:
render() {
return (
<div>
{this.state.showFirstScreen && <FirstScreen />}
{this.state.showSecondcreen && <Secondcreen />}
</div>
)
}
If that's the case, your FirstScreen component can accept a prop called something like onSubmit -- you say that you already store the input values from FirstScreen in state, so when FirstScreen is finished, you can call this.props.onSubmit(this.state) and it will send up the state to your parent component, as long as you've defined a callback function in the parent component:
{this.state.showFirstScreen && <FirstScreen onSubmit={this.onFirstScreenSubmit} />}
Then, you can save the state of the first screen into the state of your Parent component, and pass that part of the state down to SecondScreen
[edit] here's a very crude example: https://jsfiddle.net/df4s9ey8/

React Conditional Rendering on click

I have a list of poem titles and images within article HTML tags. Whenever a user clicks on an article, I want a modal to show the poem verses. As of now whenever an article is clicked, the modals for every poem opens. How do I open the modals one at a time? This is my first time using React.
Link to my codesandbox:
https://codesandbox.io/s/and-air-52dpo?fontsize=14
You need to separate each Poem card to a component, and put the state inside them.
By using state on parent component as you did, it cause all poem card depend on same state.
I've forked your codesandbox, and fixed them. You can check it.
https://codesandbox.io/embed/and-air-543tl
You're using a single show variable in your Poems component.
This doesn't allow to show a single one of your modals, as all of them are referenced to this same variable.
I would use an integer in the Poems's state - rather than the boolean show - to store the currently presented modal.
The best option for this integer is probably the poem's index, as you should anyway add to your map function:
const listItems = data.map((poem, index) => (
<React.Fragment key={index}>
// The rest of your code is the same
<Modal
show={this.state.currentModal === index} // only this property was updated
onClose={this.showModal}
title={poem.title}
>
// modal code
</Modal>
</React.Fragment>
))

Go back to the App component without react routing

I have the component that displays one button. Clicking this button loads the component which has a back button. I now want to return back to the component when this back button is clicked.
I am new to react and if I search online I see react-routing as the solution. Wouldn't simply rendering the component from component work? Just like was rendered from ?
Parent component has a state named isChildActive.
this.state = {isChildActive: false}
On the render of Parent you instantiate <ChildComponent active={this.state.isChildActive} goBack={() => this.setState({isChildActive: false})} />
And then you add to the onClick callback of the button at ParentComponent: <button onClick ={() => this.setState({isChildActive:true})} />
So that's the simple way of doing it. You own the state at your parent component because in react, data flows unidirectionally, from top to bottom. And then you pass a callback to your children components, to modify that parent owned state, when needed.
The best way of routing is using a library because it is not a simple task and you'll save a lot of time and headaches if you use a well-tested library. The industry standard is react-router

React component updates holds other component to update

I am new to React and Redux, and I have the following sample code.
```
<React.Fragment>
<Spinner />
<TableWrapper
onClick={
()=>{sendActionToToggleIsLoading();
sendActionToChangeTableData()}
}
/>
</React.Fragment>
```
Two components, a Spinner and a Table, they both use its own container to connect to the redux store.
The Spinner connects to a isLoading props and the TableWrapper connects to an array [tableData] in store.
The onClick event on TableWrapper will send two actions to change isLoading and [tableData] in the store and cause two components to update.
My problem is TableWrapper will take a bit time to update, and Spinner doesn't. However the Spinner won't update until TableWrapper finishes componentDidUpdate.
So the behavior now is after onClick, the two components both stuck for a while and then both update to the new state.
My goal is to let the Spinner to update as soon as onClick is triggered and the TableWrapper updates itself.
Am I doing something wrong?
Maybe try to dispatch the loading action inside sendActionToChangeTableData(), I cant tell you why, but it works for me

Categories