React - Calling the function of other component - reactjs

I'm very very new with React. Actually I started to learn today.
I want to build a single sidebar component in a website.
I toggle a sidebar using UseState and a function called openHandler that verifies of the sidebar is already active.
I'm wondering how should I approach the toggle inside of the sidebar. How should I change the state of the sidebar if all the handle is done in the main file (App.js)
I'm really sorry if this question don't make sense.
Here is a SandBox example of what I'm talking about.
https://codesandbox.io/s/hopeful-framework-c4k1h
If someone know what should I learn to play with that would be great.
Thanks in advance

you can pass the main handler to sidebar via props and bind it to insider toggle.
appjs
...
<CartBox openHandler= {openHandler} className={ToggleCartState} />
...
cartBox.js
...
<Toggle click={props.openHandler} />
...
Nice to read https://reactjs.org/docs/lifting-state-up.html

I assume you want to be able to change the state of the sidebar by clicking a button from another sibling / child of a sibling component.
if that's the case you'll need to put the useState hook in the higher level parent, then pass the state / an it's setter method as a prop to the children that will use it.
here is an example of what I mean.
Parent Component
function parent() {
// the sidebar state
const [sidebar, setSidebar] = useState(false);
// helper function that toggles state
function toggle() {
setSidebar(!sidebar);
}
return (
<section className="Parent">
{ /* Conditional Render */
sidebar ?
<Navbar stateManager={{toggle}} />
: <HamburgerIcon stateManager={{toggle}} />
}
</section>
)
Navbar / HumburgerIcon
function Navbar({stateManager}) {
// you now passed state and it's set method to the child
const {toggle} = stateManager;
return (
<div onClick={toggle}>
component content
</div>
}
You can put them all in same file and still do the same thing.

Related

Universal Const in React?

I have a React project with two separate components, a Header and a Sidebar. On the header there is a button which should collapsed the sidebar. I tried setting up a boolean const that would toggle a class in the Sidebar component, making the Sidebar collapsed. The only way I can think of doing this is a universal constant. Is this possible in React and/or is there a better/other way of achieving this other than merging the two components into one?
You can use context api using useContext hook. The shared state can be defined in the parent component like your layout and accessed in sidebar and header..
Hope it helps
You probably want to move the state to the parent, something along those lines:
function NavBar() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Sidebar className={isOpen && "isOpen"} />
<NavToggle onClick={() => setIsOpen(true)} />
</>
);
}
function NavToggle(props) {
return <button onClick={props.onClick}>Toggle nav!</button>
}

Why do (some) CSS styles break when I defined a React functional component inside another functional component?

Why does defining a React functional component inside another functional component break CSS transitions?
function Doohick({isOpen}: {isOpen: boolean}) {
const style = {
transition: 'opacity 2s ease',
...(isOpen ? {opacity: 1} : {opacity: 0})
}
return (
<div style={style}>
Doohick!!!
</div>
)
}
function Parent() {
const [open, isOpen] = useState(false)
return (
<>
<button onClick={() => setIsOpen(!isOpen)}>Toggle Doohick</button>
<Doohick isOpen={isOpen} />
</>
)
}
If I define Doohick outside of Parent, as above, everything works great. If I move the definition inside Parent, with no other changes, my CSS transitions break. Other CSS properties are fine.
Why does defining a functional component inside another functional component break CSS transitions?
Complicated Explanation of Why I Want To Do This
I hear you asking: why would I want to do that? I'll tell you, but bear in mind you don't need to know any of this to understand the specific problem.
I want to encapsulate the Doohick state in a custom hook:
function useDoohick() {
const [isOpen, setIsOpen] = useState(false)
const ToggleButton =
<Button onClick={() => setIsOpen(!isOpen)}>Toggle Doohick</Button>
const Doohick = <MyDoohick show={isOpen}/>
return {ToggleButton, Doohick}
}
function Parent() {
const {Doohick, ToggleButton} = useDoohick()
return (
<>
{ToggleButton}
{Doohick}
</>
)
}
But I also want the Parent to be able to pass its own props into Doohick or ToggleButton. I can almost achieve that that like this:
function useDoohick() {
const [isOpen, setIsOpen] = useState(false)
const ToggleButton = ({text}) =>
<Button
onClick={() => setIsOpen(!isOpen)}
>
{text}
</Button>
const Doohick = () =>
<MyDoohick show={isOpen} />
return {ToggleButton, Doohick}
}
function Parent() {
return (
<>
<ToggleButton text='Burninate' />
<Doohick />
</>
)
}
This works as advertised: ToggleButton renders with the expected label and controls whether or not Doohick is shown. But this pattern breaks some CSS styles (specifically, transitions) I have defined on Doohick. Other styles are fine.
I can still call it like this:
function Parent() {
return (
<>
{ToggleButton({text: 'Burninate'})}
{Doohick()}
</>
)
}
...and the transitions work correctly. But I would much prefer the standard JSX syntax here:
<ToggleButton text='Burninate />
Clearly, <Doohick /> and Doohick() are different. But what is it about the former that breaks CSS transitions here?
The root of the problem boils down to defining the custom components inside the Parent. The hook itself is irrelevant. But this pattern of encapsulating state in a custom hook while returning a customizable component is really powerful and almost works, so I'm hoping there's a way it can be saved.
TL;DR
Why does defining a component within another component break my CSS transitions (and possibly other styles I haven't found yet)? How can I get around this while still calling my nested component with JSX-style syntax?
Defining a component inside another component will always result in issues like this. Every time the outer component renders, you create a brand new definition of the inner component. It may have the same text as the one from the previous render, but it's a different function in memory, so as far as react can tell it's a different type of component.
The component type is the main thing that react looks for when reconciling changes. Since the type changed, react is forced to unmount the old component and then mount the new one. So rather than having a <div> on the page who's style is changing, you have a div with some style, then it gets deleted and an unrelated div gets put onto the page. It may have a different style, but since this is a brand new div, the transition property won't do anything.

When Reactjs has functional component as parent and child component as class

I am new in reactjs and learning bit and pieces. I am facing an issue. The scenario is like. I have a functional component as a parent. It has a child component as a class component. I would like to set or reset the child component's state on parent's button click. Or is there any way to call the child component's any method from the parent component. I tried as
// this call from a functional component.
<PhotoPreviewUploaend setSelectedFile={setSelectedFile} ref={setImagePreviewUrl} />
Later after a button click does this:-
setImagePreviewUrl('');
I read ref attribute allows access to the component. I tried this ref between 2 class component both parent and child is class components and it works as expected. But when did the same from a functional component it has no effect at all. How can I do it?
You are not embracing react one-way data flow by using refs like that; it might not behave the way you expect;
You should pass parent state handler logic function to the child component,
then child component call it with proper value; as the result your parent state will be updated and you have nice and clean one way data flow; you can use this in any kind of component, since you don't mess with this bindings in functional components;
This example demonstrates it in action:
function App() {
// Define your state
const [someState, setSomeState] = useState(0);
return (
<div className="container">
<Child parentCallback={setSomeState} />
</div>
);
}
class Child extends Component {
render(){
return(
<div>
<button
onClick={() => this.props.parentCallback(/*someValue*/)}
>
click me!
</button>
</div>
)
}
}

React renders full component instead of what changed when using wrapper function

I observed below when rendering a list component. The list component is taking a search prop and filtering before rendering.
<UserList pattern={search}/>
when using above statement directly inside parent component, it renders only what changed based on search prop (list remains and only unmatched items got removed)
But when I wrap the UserList in another function like below:
const Users = ()=> <UserList pattern={search}/>;
and use <Users/> in parent component, I see that whole list component re-renders when search prop changes. search field is a local state (useState['']).
so, the parent component looks like this now :
const App = () => {
const [search, setSearch] = useState('');
const Users = ()=> <UserList pattern={search}/>;
return (
<div id="app" className="home-page">
<Header />
<WelcomeSlogan/>
<Users/>
</div>
);
}
So we know that react re renders full child component(s) if parent component changed, but in this case how the parent (<Users>) is changing exactly? Can someone explain to help me understand better? Thanks.

Should i use State or Props in this simple ReactJS page?

i'm rebuilding my portfolio with ReactJS as i'm learning this new language and i have 1 question. Should i use state or props only in a website where no content will need to be updated?
This is my main class:
class App extends Component {
state = {
name: 'My name',
job: 'Desenvolvedor Web'
}
render() {
return (
<div className="App">
<Header name={this.state.name} job={this.state.job}/>
</div>
);
}
}
And this is my Header.js
const Header = (props) => {
return(
<div className="Header">
<div className="conteudo text-center">
<img src="" className="rounded img-circle"/>
<h1>{props.name}</h1>
<h2>{props.job}</h2>
</div>
)
}
I guess my entire one page portfolio will follow this structure path, with not a big use of handles and changes in my DOM.
I'm sorry for this noob question, i'm really trying my best to learn React.
You should use both state and props in conjunction with one another. You're using both in your code perfectly fine. State is something that is managed by a component and can be passed down to a child via the props. A simple way of understanding this is that you can pass down the Parent component's state (App) to the child (Header) in the form of props which is an important concept in React.
State is both readable and writable whereas props are read only. Also, any change in the components state triggers a re-render.
Here, your state acts as the top/root level for the data that can be passed down to other components if it needs to be used again.
See these for more info.
What is the difference between state and props in React?
https://flaviocopes.com/react-state-vs-props/
State is for properties of your component that change and in turn cause your component to re-render. If you are only passing data down to read, props are a more appropriate choice.

Resources