How to set state of a childcomponent in react? - javascript

In my React component called Grid.js I am using a childcomponent called Pagination. It looks like this:
<StyledBox wrap py={12} px={18}>
<Header />
{state.data}
<Wrapper column justify="center" align="center" p={12}>
<Pagination onChange={this.handleChange} totalPages={10} />
</Wrapper>
</StyledBox>
It is a grid with some pagination functionality. When the user selects a page on the Pagination a changeevent will fire and a stateprop of the Grid will be set called state.data. The issue is that the pagination starts jumping around randomly: looks like the state has changed on the component.
Do I have to move the Pagination out of the Grid component and make it not a childcomponent?

Is the Pagination Component jumping around randomly because previously there was a specific length of data. Then when the this.state.data changes, the length of data is different? So then, the Pagination had to adjust it's positioning. Without more information, it seems like a HTML and CSS issue.
Try to set position: fixed; bottom: 1rem on the Pagination component css and see if it still jumps.
Also, regarding React Components, <Content /> and <Pagination /> components seem to be conceptually sibling and not parent-child related. So I would structure the app something like this:
<ParentContainer>
<Header />
<Content data={this.state.data} />
<Pagination onChange={this.handleChange} totalPages={10} />
</ParentContainer>

Related

How to implement data update from one component which might affect other components

I am implementing a todo application which has several pages where each page displays a filtered list of all todos depending on the todos' references.
In addition, there is a global "Add task" button and modal from which users can add a task with references. Depending on which page the user is on when adding a task, this newly added task must either be shown right away because the reference is included in currently active page's filter or it must not be shown.
For example, if the user is on the page "Project 1"
If user adds task for Project 1 -> show on page
If user adds task for Project 2 -> don't show on page
Currently, App.js looks something like this
function App() {
return (
<Page>
<Router>
<Route path="/project1" element={<TaskListProject1 />} />
<Route path="/project2" element={<TaskListProject2 />} />
<Router />
<AddTaskButtonAndModal />
<Page />
);
}
How do I best set up and manage the state so that the components TaskListProject1 and TaskListProject2 are only updated if the added task must be included there?
I was thinking about adding the task from the AddTaskButtonAndModal component to the data base and then let the currently active component retrieve all their tasks from the data base again. For this, I would introduce a dummy state whose sole purpose is triggering a rerender of components like so
function App() {
const [dummyState, setDummyState] = useState(0);
return (
<Page>
<Router>
<Route path="/project1" element={<TaskListProject1 dummyState={dummyState} />} />
<Route path="/project2" element={<TaskListProject2 dummyState={dummyState} />} />
<Router />
<AddTaskButtonAndModal setDummyState={setDummyState} />
<Page />
);
}
...but that feels like I'm misusing states.
Another idea was to always have a complete list of all tasks in the top level state and let each component filter for their tasks when it is rendered. But then I need to always have all tasks in the state when only a fraction of tasks are actually needed.
As you can probably imagine, I'm new to React, so I might simply miss a basic concept. Thanks for any help!

Updating child props value on parent props value change

guys! I'm building React Native component that contains a UI pattern. This UI pattern will contain several smaller reusable patterns. This way:
<ListItem onPress={}>
<IconContainer>
<Icon />
</IconContainer>
<Body>
<Text>Content</Text>
</Body>
<Right>
<Action onPress={} />
</Right>
<ListItem>
Now I'm also building embedding size variants (small, medium/default and large) for some of these children, like this for example:
<IconContainer large={boolean} small={boolean}>
<Icon />
</IconContainer>
And since the are several children, I don't want to have the person using the component to have to specify the size variant for each one of the children. That'll also require them to know which one of the children have size variants and which one doesn't.
So, what I'm trying to do is to embed a props.large and a props.small into the parent and use that to change de value of the same prop if available in the children.
Any ideas of how to do that in a simple way?
(I suspect this is easy but I've been struggling with this for a while so I thought I'd ask for some help.)
Thanks in advance!

React Router Link dont updated page data

I have this react + redux app
I have 1 Movie component with some movie data displayed on it which are fetched from API.
So at the bottom, i decided to add a Similar movies section with a couple of components to navigate to the new movie pages.
<div className="similar_movieS_container">
{ this.props.thisMovieIdDataSIMILAR.slice(0,4).map((movie,index)=>{
return(
<Link to={"/movie/"+movie.id} key={index}>
<div className="similar_movie_container">
<div className="similar_movie_img_holder">
<img src={"http://image.tmdb.org/t/p/w185/"+movie.poster_path} className="similar_movie_img" alt=""/>
</div>
</div>
</Link>
)
})
}
</div>
Now when I'm at a root route for instance /toprated and i click on a <Link to={"/movie/"+movie.id} key={index}> i get navigated to the particular route (e.g. /movie/234525 ) and everything works fine , but if I'm in a /movies/{some move ID } route and i click on some <Link to={"/movie/"+movie.id} key={index}> The route in the URL bar gets updated, but the page stays still, meaning nothing changes if I reload the page with the new route the new movieID data is displayed...
So how can i make a navigation to a new /movie/{movieID} FOMR a /movie/{movieID} ?
It's because you are just within same route.
There are few ways to work around this. I bet you are rendering routes like this.
<Route path="/movie/:id" component={Movie} />
Try like this.
<Route path="/movie/:id" component={() => <Movie />} />
Another solution would be to use componentWillReceiveProps instead of componentWillMount.
This happens because the component of page movie was mounted, so the render method of this component will not be mounted again or updated, so you need to fire a code to change the state, and consequently re-rendering the page content, for this you can implement the componentDidUpdate method which is fired for every props modification.
https://reactjs.org/docs/react-component.html#componentdidupdate
Basically you implement the same code above inside

How to replace React-Leaflet Popup with custom component?

I'm using React-Leaflet and (callemall)Material-UI in a project. I'm attempting to render the Material-UI Card component within the <Popup></Popup> component of React-Leaflet. I've tried pulling it into the Popup as a component but the popup doesn't let the component work as it should. Specifically, the card component has a button element that expands it but unfortunately, the popup won't let me click it. I'm sure there's some CSS-y thing that I need to override but my thought is that an easier option would be to just replace the popup component with my own component but I'm not sure how to go about doing so. Any insight is much appreciated :)
My code looks like this:
<Marker position={position}>
<Popup>
<MapPopup />
</Popup>
</Marker>
And the imported component looks like: (I've removed styles and unimportant details to make it simple to read)
<Card>
<CardHeader />
<CardMedia
expandable={true}
overlay={
<CardText expandable={true}>
<div>
<p>Text</p>
<Chip>text</Chip>
</div>
<div>
<p>Text</p>
<Chip>Text</Chip>
</div>
</CardText>
}>
<img src="cardMediaImageURL" />
</CardMedia>
</Card>
Long story short, React-Leaflet and Leaflet renders static html for the popup so it is not possible to render dynamic content within it. Rendering a material-ui component is possible, however it won't be interactive. You can accomplish this by wrapping your component with <MuiThemeProvider></MuiThemeProvider>. You just have to make sure that you have the content set to be the complete view and not with anything like an expander.
Solution is as follows:
<Popup>
<MuiThemeProvider muiTheme={getMuiTheme(yourThemeName)}>
<YourCustomComponent />
</MuiThemeProvider>
</Popup>

How to customize nested components?

How to customize nested components?
I'm building React Native app with Redux.
I have three screens in my app that render list of users.
Follower/Following should show FollowButton:
<FollowersContainer>
<UserList onFollow={func} onUnfollow={func} users={[...]}>
<UserCard user={user} onFollow={func} onUnfollow={func}>
<FollowButton onFollow={func} onUnfollow={func} isFollowing={bool} userId={string} />
</UserCard>
</UserList>
</FollowersContainer>
Ask question screen should show AskButton:
<AskQuestionContainer>
<UserList onAsk={func} users={[...]}>
<UserCard user={user} onAsk={func}>
<AskButton onPress={onAsk} />
</UserCard>
</UserList>
</AskQuestionContainer>
Search Results should not show any button
<SearchResultsContainer>
<UserList users={[...]}>
<UserCard user={user} />
</UserList>
</SearchResultsContainer>
As you can see, all three screens uses UserList and UserCard components.
Currently UserList and UserCard needs to know about onFollow onUnfollow and onAsk actions and how to pass them around.
This can get complicated and not very flexible.
Ideally I want to do something like:
<UserList
rowComponent={
<UserCard button={<FollowButton />} />
}
/>
But how do I pass the actions from the top level component into the actual button? and How do I know which actions to pass?
I could use connect on the actual buttons to pass them the actions directly but I prefer these components stay pure and flexible.
Any suggestion on how to solve it in a clean way?
Thanks,
Ran.
You can pass components as a prop.
render() {
var passedButton = (<FollowButtton />);
var row = (<UserCard button={passedButton} />);
return (
<UserList rowComponent={row}/>
);
};

Categories

Resources