React component composition - reactjs

I trying to build a simple slide show using react (I am learning react) and have a question regarding the component composition/information flow.
I have a slides component which has two child components. One child, the slideContainer, displays the slide and the other component, the slideNavigation displays the navigation buttons (back/next).
The slides component receives the slides collection as prop and has the currentSlide as State. The slideNavigation component receives the currentSlide, the slides collection and the setCurrentSlide callback as props.
The slideNavigation component determines the new currentSlide based upon the button that was clicked, the slide collection and the currentSlide. The new currentSlide is returned to the slides component using the callBack. The slides component updates the state accordingly and passes it to the display component, which displays the new slide. See the code of the slides component below.
My question: It seems a bit weird to determine the new currentSlide in the navigation component, pass to back to its parent which passes it again to the navigation component where it just came from. Am i doing something wrong, are the components correctly composed??

You should add callbacks/props to your slidenavigation like:
onPrevSlideButtonClicked
onNextSlideButtonClicked
Then in your parent component you will add callbacks for each event and calculate the new slide (because that is where all your info is stored).

The only change that you can make is to move the determination of the new slide, from the slideNavigation to the parent slides component.
The slides component should hold the state and be responsible for managing it. It contains 2 dumb child components, the slideContainer and the slideNavigation. These child components should know nothing about what is going on; the Container should just show what it receives from the parent and the navigation should just return events that occur (the next and previous button clicks)
It should be the job of the parent slides container to manage the state transition by sending props down to the slideNavigation component, which would be tied to the buttons for the next and previous actions.

Related

React app confusion setting state of nested child component

I'm an embedded developer who is new to React and am struggling a bit with the behaviour of child components and nested child components.
I understand that for any component to be re-rendered, the state must change. I am using an example of a menu component that has an item component within. When some global level event happens, I want to change the text displayed by the item components.
Here is a fiddle that shows some code that I would expect to work:
https://codesandbox.io/s/dark-rain-8mfsp?file=/src/App.tsx
On clicking the div, the menu's setText function gets called, which calls into the item component, setting the state. This state is used in the render function of the item component, so I would expect both item and menu to be re-rendered.
Instead I get an error saying that I can't set the state of an object that hasn't yet been mounted. I would have thought it had been mounted..
Perhaps the way I have linked the declared components with those in the render functions by calling this.componentname.render() is the issue - but how else could that be done?
Thanks in advance!
Here is a working version of your sandbox.
https://codesandbox.io/s/lucid-bird-qecj0?file=/src/App.tsx:0-899
I see that you are new to react. I would suggest you use hooks instead of class components.

Hiding Components in order to keep their state in React

I have a component with children. I would like these to be shown or not depending on the press of a button. I can do this by creating a state variable childrenVisible, and then rendering or not depending on it.
But I have noticed that if I have state on a child Component it will get reset when toggling childrenVisible. I think this is because components gets destroyed when not rendered on a re-render.
I would like to keep the elements around, so I can keep their state, but just hide them depending on childrenVisible. Is this possible in React?

React check if component is in focus from a TabView

I have a TabView component that has multiple tabs containing components. These components have entire hierarchies of other components. How could I know from any child component nested arbitrarily deep in one of these hierarchies whether or not it's parent tab is in focus in the TabView?
Preferably, I would want to implement this similar to react-navigation's withNavigationFocus (or an equivalent hook) so that any component can know if it's in tab focus without having to pass props down the chain of components. I'm thinking you could have a TabViewContext that components can register themselves as focus listeners to by doing a useContext. The TabViewContext would be provided by the TabView and the TabView would be responsible for determining what registered listeners are in focus when tabs change. My dilemma is I don't know how the TabView could determine efficiently what nested child components come into focus when the tab changes. Any ideas?
In case the other parent tabs are hidden, you could test for visibility in plain JS, rather than have a much more complex solution...
Checkout this answer on how to do this.
So components that care about the visibility of their parent tab could use a ref for their own DOM elements and test whether they're visible or not. You could build this into a simple helper function or a hook
EDIT:
I'd suggest going with something like this:
Each Tab will provide a context with method for any descendant to register a callback that will be called when the Tab is hidden. The TabView can pass a "isVisible" prop to each tab (if it doesn't already), so Tab can know when its display changes.
When a Tab changes from visible to hidden. All registered callbacks will be called.
I would of course write a hook or a helper function to create this TabVisibilty context so each Tab component can use it in a reusable manner.

React App Prevent Rerender of All Items in Grid When Redux Updates

I've got an app that shows a list of items in a grid. Some of the items have an embedded video which flashes or stops playing (if it's already playing) when it's rerendered.
The list is maintained in Redux. When the user scrolls to the bottom of the page it loads more results which causes the Redux state to update which, in turn, causes the grid to rerender all of the items plus the new items.
I'm looking for a solution that will just add more items to the end of the grid instead of rerendering everything.
I've got a component that holds the entire grid. It renders a component for each item in the grid. In each item I have a component that holds the embedded video.
Any ideas?
If each item in the grid is a component, like you said, you should use React.memo (for functional compoents) or Reat.PureComponent (for class components). It will prevent the component from rerendering if the props have not changed. I can't guarantee your videos will keep playing, but if the only reason they stop playing or flash is because the component is being rerendered then it should fix the problem.
Maybe this can help: when passing information from redux to your component, try to update the list of the objects instead of sending a new one
It's redux UpdateObject method.

Finding parent refs

I have a <Skylight ref="foo".... /> component in my main Layout. How would I show the modal dialog of Skylight from a child component?
I mean, how would I call this.refs.foo.show() in my component and make this.refs.foo point to the Skylight component that is 3 or 4 levels up in the DOM?
You could introduce a top-level container component for modal dialogs, that populates its children based on the state of a collection in your top-level store. Then the child component could dispatch an action to create a modal dialog.
I implemented something similar for toast-style notifications; will post an example when I'm back at a keyboard...

Resources