component hiding - reactjs

In react, There is one component A inside there is one component B I have used. There is one more component C, and inside C there is one button which is when clicked it hides the component B from component A.
How can I achieve this functionality

Using only React, you can achieve this by:
Parent/root component to all of these components has a boolean state, let's call it showComponentB. It's initialized to true.
This root component passes down the state showComponentB as a prop to Component A. In Component A, it is used to either show Component B if showComponentB is true or hide if it's false.
Root component passes a function to alter the state of showComponentB into Component C and is called when the button is clicked.
State of showComponentB is updated in root to false and that updated value is passed through to Component A and hides Component B.

You can try something like this. Hope it helps you.
import { useState } from "react";
import "./styles.css";
export default function App() {
const [isVisible, setIsVisible] = useState(true)
return (
<div className="App">
<CompA>
{isVisible && <CompB>
<CompC clickHandler={()=>setIsVisible(false)}/>
</CompB> }
</CompA>
</div>
);
}
export const CompA = (props) => {
return <>
<div style={{backgroundColor:'red', height:'200px',width:'200px'}}>Component A
{props.children}
</div>
</>}
export const CompB = (props) => {
return <>
<div style={{backgroundColor:'blue', height:'150px',width:'150px'}}>Component B
{props.children}
</div>
</>
}
export const CompC = (props) => {
return <>
<div style={{backgroundColor:'green', height:'100px',width:'100px'}}>Component C
<button onClick={props.clickHandler}>hide B</button>
</div>
</>
}

Related

can we able to specify on click on the component definition itself?

I want to create a component(comp) with onclick event handler. which should be handled by the component itself (i.e. inside the comp.js file).
if I use it inside the parent component we don't need to specify the event but it is handled by the component element(comp element).
is this possible. Any idea to develop this one.
in ParentComponent.js current behavior.
<NewComponent onClick={clickBehaviour}/>
I want like,
In NewComponent.js
const NewComponent.js = ()=>{
// Some code
const clickBehaviour = () =>{
// click behaviour
}
}
Is it possible in the current standards?
why you want to write your onClick event in parent component?
you can do it inside NewComponent.js easily.
just do this:
import React from 'react'
function NewComponent() {
const clickBehaviour = () =>{
// click behaviour
}
return (
<div onClick={clickBehaviour}>
//some jsx here
</div>
)
}
export default NewComponent
and use in anywhere you want to use without onClick event :
< NewComponent />
i cant understand well you situation but you can use forwardRef if you want (also can use old getElementById but using forwardRef is recommended).
import React, { useRef } from "react";
const NewComponent = React.forwardRef((props, ref) => (
<div onClick={() => alert("div 2 clicked")} ref={ref}>
div 2
</div>
));
export default function App() {
const compRef = useRef(null);
return (
<div>
<NewComponent ref={compRef} onClick={() => {
compRef && compRef.current && compRef.current.click();
}} />
</div>
);
}

Pass state onto {children} React hook

So I have a component that looks like this:
import React, { memo, useState } from "react";
import styles from "./navigation.styles.scss";
const Navigation = ({ children }) => {
const [toggle, toggleState] = useState(false);
return (
<>
<div onClick={() => toggleState(!toggle)}>
<p>Test</p>
</div>
{children}
<style jsx>{styles}</style>
</>
);
};
export default memo(Navigation);
And then I have another component that looks like this:
import React, { memo, useState } from "react";
import styles from "./container.styles.scss";
const Container = ({ children }) => {
const [toggle, toggleState] = useState(false);
return (
<>
<div className={toggle ? "dark-bg" : "dark-bg active"}>
{children}
</div>
<style jsx>{styles}</style>
</>
);
};
export default Container ;
Now, the thing is the {children} of the 1st component is sometimes the 2nd component, and sometimes it's not. Therefore I can't just put the CSS and HTML from the 2ndcomponent into the 1st component - which in turn would fix my problem.
But as you might be able to see, there is an onClick event in the first component. I would like it so that when that is clicked, the state from the click is send to the 2nd component and toggles the className-toggle.
Can this be achieved by doing this, or do I have to set everything up differently ?
And yes, I am quite new to React, so please don't be harsh.
Css
I would look into better methods of applying styling with css. Not sure about your project scope/tools but typically all the css files are imported in the dom root and loaded in there. This avoids creating css files for every component.
Here's 9 ways of implementing css for react.
Passing HTML
In react if you want to render component in another component instead of passing it as a child you should import it as follows.
// replace container path with actual path of Container file
// ex './Container.js'
import Container from 'container_path.js';
Now Rendering the Component is as simple as including it in the html code.
return (
<>
<div className={toggle ? "dark-bg" : "dark-bg active"}>
<Container/>
</div>
</>
);
Here's a Stack Overflow post of users importing components using react + es6 + webpack. More information on importing components is available there.
State management
In react if you have a state that is being accessed by multiple components the standard is to keep the state in the parent component.
This way you can pass the state as a prop to any children components. You can also create a function which updates this state and pass that function as a prop to the children.
ex:
import React, { useState } from "react";
import Container from "./Container.js";
import Navigation from "./Navigation.js"
const Parent = props => {
const [toggle, toggleState] = useState(false);
return (
<div>
<Container toggleState={toggleState} toggle={toggle} />
<Navigation toggleState={toggleState} toggle={toggle} />
</div>
)
}
Before continuing working on your project I would recommend researching functional components vs class components. Here's a helpful article.
Try to wrap second component to function with state from first component as argument.
Wrapper for your second component and using for first component
const putInnerComponent = (stateFromOuterComponent) => <Container toggle={stateFromOuterComponent}/>;
<Navigation children={putInnerComponent}/>
Your first component
import React, { memo, useState } from "react";
import styles from "./navigation.styles.scss";
const Navigation = ({ children }) => {
const [toggle, toggleState] = useState(false);
return (
<>
<div onClick={() => toggleState(!toggle)}>
<p>Test</p>
</div>
{children(toggle)}
<style jsx>{styles}</style>
</>
);
};
export default memo(Navigation);
Your second component
import React, { memo, useState } from "react";
import styles from "./container.styles.scss";
const Container = ({ children, toggle }) => {
//const [toggle, toggleState] = useState(false);
return (
<>
<div className={toggle ? "dark-bg" : "dark-bg active"}>
{children}
</div>
<style jsx>{styles}</style>
</>
);
};
export default Container;

How to toggle class of a div element by clicking on a button that is inside another functional component (another file)?

I want to toggle class of container (file 2) by an onClick on the button that is inside another component file.
The button has already an onClick function and I want to make it so it calls on two functions. Two toggle functions for the button and two class toggles for the container.
Hope it makes sense.
Here is my code so far:
Button component (File 1)
import React, {useState} from "react";
import "./Sort.scss";
const Sort = () => {
const [toggleSortIcon, toggleSortIconSet] = useState(false);
return (
<div className="tools">
<button
onClick={() => toggleSortIconSet(!toggleSortIcon)}
className={`sort ${toggleSortIcon ? "horizontal" : "vertical"}`}>
</button>
</div>
);
}
export default Sort;
Div container component that I want to change the class of (File 2)
import React, {useState} from "react";
import "./WordContainer.scss";
import UseAnimations from "react-useanimations";
const WordContainer = ({title, definition, example}) => {
const [toggleSize, toggleSizeState] = useState(false);
return (
<div className={`container ${toggleSize ? "big" : "small"}`}>
<div className="content">
<h2>{title}</h2>
<p>{definition}</p>
<h3>Example</h3>
<p>{example}</p>
</div>
<img onClick={() => toggleSizeState(!toggleSize)} src="./resize.svg" alt="resize" className="resize"/>
<div className="bookmark">
<UseAnimations
animationKey="bookmark"
size={26}
/>
</div>
</div>
);
}
export default WordContainer;
You could either have a global state management system (redux, or with custom hooks) that you can use to store the icon size.
Or you could simply provide a callback to your component that stores the icon size in a parent component that then feeds it back to your
Something like this:
const [size, setSize] = useState(/* default value */);
render() {
<>
<Sort onSizeToggle={setSize} />
<WordContainer size={size} />
</>
}

How to add {props.children} to a React component

i have many components which have {props.children} deeply nested inside.
considery DRY principle is there a way to add this using some React pattern.
example
let's say i have two components,
Comp1.js
import React from "react";
const Comp1 = props => {
return (
<div>
<h1>{props.children}</h1>
</div>
);
};
export default Comp1;
Comp2.js
import React from "react";
const Comp2 = props => {
return (
<div>
<div>
<h1>{props.children}</h1>
</div>
</div>
);
};
export default Comp2;
if you see above code we have both Comp1 and Comp2 have line of code {props.children} repeated inside.
what i want now is some function which will add this line of code, something like below,
const addPropsChildrenToComp = (Comp)=>{
return(
(props)=>{
///do somehting here
}
)
}
const Comp1 = props => {
return (
<div>
<h1></h1>
</div>
);
};
Comp1WithPropsChildren = addPropsChildrenToComp(Comp1)
using HOC doesn't work because, in HOC we never modify passed component.
anyway to aceve this.?
to get more idea of my problem see this demo: https://codesandbox.io/s/trusting-http-pd1yu
in there i woul like to see CompWithPropsChildren component render props.children inside it.
I think I see what you're trying to get to, and you can accomplish this just using another component.
import React from "react";
import ChildComp from "./ChildComp";
const Comp1 = props => {
return (
<div>
<ChildComp {...props} />
</div>
);
};
export default Comp1;
import React from "react";
const ChildComp = props => {
return <h1>{props.children}</h1>
}
Assuming your ChildComp has some complex logic you don't want to duplicate, this will make it reusable for you.

How to use React hooks to determine if sidebar should show?

I have read some introductions on React Hooks and want to make a simple app with a button in the header component, which determines if the main app should show the sidebar. The button sets the variable showSidebar in the header, and I want to read it again within my main component. The code for actually showing the sidebar is stripped out for brevity.
This is index.js:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Header from "./header";
import "./styles.css";
function App() {
const [showSidebar, setShowSidebar] = useState(true);
return (
<div className="App">
<Header />
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
And this is the header.js:
import React, { useState } from "react";
export default function Header() {
const [showSideBar, setShowSidebar] = useState(true);
const toggleSidebar = () => setShowSidebar(!showSideBar);
return (
<header>
Button in header toggles sidebar:
<button onClick={() => toggleSidebar()}>
Toggle sidebar (state: {showSideBar.toString()})
</button>
</header>
);
}
I am new to React, but do not understand why the state does not update in index.js? I also made a CodeSandbox with the code.
useState is stores local state, for comparison you can think of it similar to setState in a class component (although in reality they aren't exactly equivalent). Therefore, setting setShowSidebar in App won't reflect the same value as that set in Header and vice versa.
It doesn't look like Header needs any form of local state if it's simply changing state of the outer component, you can pass in an event handler and any relevant state Header needs as props instead
index.js
function App() {
const [showSidebar, setShowSidebar] = useState(true);
const toggleSidebar = useCallback(() => setShowSidebar(value => !value));
return (
<div className="App">
<Header onClick={toggleSidebar} showSideBar={showSidebar} />
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
);
}
header.js
export default function Header(props) {
return (
<header>
Button in header toggles sidebar:
<button onClick={props.onClick}>
Toggle sidebar (state: {props.showSideBar.toString()})
</button>
</header>
);
}
What you're doing wrong is declaring a separate state in Header which you shouldn't do, because it has nothing to do with parent's state. Pass the parent state and a callback to update the parent state as a props to the header. Pass showSidebar as props to the Header component:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Header from "./header";
import "./styles.css";
function App() {
const [showSidebar, setShowSidebar] = useState(true);
return (
<div className="App">
// Pass prop here
<Header
showSidebar={showSidebar}
toggleSidebar={()=>{setShowSidebar(!showSidebar)}}
/>
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
);
}
// and then in your Header,
export default function Header(props) {
return (
<header>
Button in header toggles sidebar:
<button onClick={props.toggleSideBar}>
Toggle sidebar (state: {props.showSideBar.toString()})
</button>
</header>
);
}
You want to keep state showSidebar in the parent component (where you need to read it) and pass the functionality to change it to the header component (where you need to change showSidebar)
To do move toggleSidebar to index.js
const toggleSidebar = () => setShowSidebar(!showSideBar);
and pass the function to the Header component like this
<Header toggleSidebar={toggleSidebar} />
now invoke it on clickEvent in Header component like this
<button onClick={() => toggleSidebar()}>
remember to include the prop in your Header component
export default function Header({toggleSidebar}) {
You should have your toggleSidebar function in App.js itself, and pass toggleSidebar function and showSidebar state in Header component as props.
App.js
function App() {
const [showSidebar, setShowSidebar] = useState(true)
const toggleSidebar = () => setShowSidebar(!showSidebar)
return (
<div className="App">
<Header showSideBar={showSidebar} onClick={toggleSidebar} />
<h1>Sidebar toggler</h1>
<p>
Should I show sidebar? <b>{showSidebar.toString()}</b>
</p>
</div>
)
}
Header.js
import React from 'react'
export default function Header(props) {
return (
<header>
Button in header toggles sidebar:
<button onClick={props.onClick}>
Toggle sidebar (state: {props.showSideBar.toString()})
</button>
</header>
)
}
Demo

Resources