React - functional component container - javascript

I would like to create a container component in my application. I don't know if this is possible or if it's a good idea at all. I would be so very comfortable.
From this:
export default function App(){
return(
<div className={styles.CardsContainer}>
<CardPrice price={700}/>
<CardPrice price={3000}/>
<CardPrice price={5000}/>
</div>
)
}
I want to do it:
export default function App(){
return(
<CardsContainer>
<CardPrice price={700}/>
<CardPrice price={3000}/>
<CardPrice price={5000}/>
</CardsContainer>
)
}
I do this in CardsContainer:
export default function CardsContainer(){
return(
<div className={styles.CardsContainer}>
</div>
)
}
Obviously it doesn't work) But I don't know how to wrap properly.
I don't want to put components with CardPrice in a CardContainer component. I want to wrap in App component

u can use this, but you will need to take de props.chidlren inside the container.
export default function CardsContainer({children}){
return(
<div className={styles.CardsContainer}>
{children}
</div>
)
}
but I think will be better if u use the styled component to create de container

You need to pass the elements as children to the CardsContainer and in CardsContainer component you can access it using the children prop. For a better understanding, you could refer these docs: https://reactjs.org/docs/composition-vs-inheritance.html#containment
export default function CardsContainer({children}){
return(
<div className={styles.CardsContainer}>
{children}
</div>
)

Related

How can I call the function of a parent component inside of a child component?

First off, I'm newer to react so please feel free to critique any sort of architectural problems I have, I feel like there's a better way to write this but I've been struggling for an hour trying to get it to work.
Parent Element (TileGrid):
import React, { Component } from 'react'
import Tile from './Tile.js';
export default class TileGrid extends Component {
constructor(props) {
super(props);
}
updateTileData(value) {
{/* Do something with value here */}
}
render() {
this.test()
return (
{/* The Tile component is a custom button with some richer features. */}
<Tile name='Dog' image='dog' />
)
}
}
Child Element (Tile):
import React from 'react';
import ButtonBase from '#mui/material/ButtonBase';
import './styles/Tile.css';
function Tile(props) {
return(
<div className="Tile">
<ButtonBase onClick={/* This is where the Tile needs to call updateTileData in TileGrid */}>
Button
</ButtonBase>
</div>
);
}
export default Tile;
So there's a function inside of TileGrid called updateTileData that is going to take some data and use it to update the state of TileGrid. The Tile component exists as a child within the TileGrid component. I've tried all sorts of stuff on here but this seems like a simple task to do, is there a better way to write this functionality? I'm not tied down to anything in the code, please tell me if there's a better way to do this. I'm still learning this framework and this issue has me hung up. Thanks, Archer.
pass the function from parent to child as a prop example :
<Child func={this.functionInParent} />
props.func() //called inside child
you need to pass a prop to child Element and Call it.
import React, { Component } from 'react'
import Tile from './Tile.js';
export default class TileGrid extends Component {
updateTileData(value) {
{/* Do something with value here */}
}
render() {
this.test()
return (
{/* The Tile component is a custom button with some richer features. */}
<Tile name='Dog' image='dog' setValue={this.updateTileData} />
)
}
}
child Element :
import React from 'react';
import ButtonBase from '#mui/material/ButtonBase';
import './styles/Tile.css';
function Tile(props) {
return(
<div className="Tile">
<ButtonBase onClick={()=>props.setValue("your value")}>
Button
</ButtonBase>
</div>
);
}
export default Tile;

in React, how to call a function living in another component?

in my react's App.js's return i am currently calling this.searchVenues() in a way that works but is messy and i know there is a better way. The searchVenues() function lives in App.js and I have buttons that need to be in their own component, then just <ButtonComponent/> instead of:
render() {
return (
<div className="App container-fluid">
<Navbar/>
<div className="row">
<div className="col-xs-3">
<button onClick ={() => this.searchVenues("yoga+coffee", "5")}>5</button>
<button onClick ={() => this.searchVenues("yoga+coffee", "10")}>10</button>
<button onClick ={() => this.searchVenues("yoga+coffee", "15")}>15</button>
<SideBar {...this.state} handleListItemClick={this.handleListItemClick}/>
</div>
<div className="col-md-9 full-height">
<Map {...this.state}
handleMarkerClick={this.handleMarkerClick}/>
</div>
</div>
<Footer/>
</div>
);
}
but when i do this.searchVenues("yoga+coffee", "5") does not work, understandably so. What's the best or a better way to make it work? How do i access the function from another file ( component )?
I believe you want to declare your searchVenues func in App.js component like this:
searchVenues = (arg1, arg2) => {here is the body of your function}
... and pass it down to the ButtonComponent using props:
<ButtonComponent searchVenues={this.searchVenues}
Once you are in your stateless ButtonComponent, you can create a new function inside it if you want to avoid anonymous functions in your render (you can read on it here)
const searchVenues = (arg1, arg2) => {
return event => {props.searchVenues(arg1, arg2);}
}
... and add it to the onClick event:
<button onClick ={searchVenues('coffee+yoga', props.value)}>{props.value}</button>
If you want your buttons to live in another component, but receive handlers from another component, you can pass them down through props.
import React, { Component } from 'react'
import MyButton from './MyButton'
export default class App extends Component {
buttonClickHandler= () => {
alert('I have been clicked!')
}
render = () => (
<MyButton onClickHandler={this.buttonClickHandler} />
)
}
And here is the MyButton component file:
import React from 'react'
const MyButton = (props) => (
<button onClick={props.onClickHandler}>Click Me for an Alert!</button>
)
export default MyButton
You could either have searchVenues defined in your ButtonComponent or pass it to ButtonComponent as a prop. Then in your ButtonComponent render function you would do the same thing:
<button onClick ={() => this.searchVenues("yoga+coffee", "15")}>15</button>
or if it is passed as a prop
<button onClick ={() => this.props.searchVenues("yoga+coffee", "15")}>15</button>
I will also add that #Bryan is absolutely right about services. Lets say for instance you have a table in a database called Product. Well, you don't want to implement getAllProducts() in every component that needs a list of products. Instead, you would create a class called ProductService where getAllProducts() would be defined. Then, for any component that needs a list of products, you would import the ProductService class and call ProductService.getAllProducts().
Hope that helps.
If you want to execute methods from any component, and the result of those methods will change the global state of the app, you might benefit from using actions.
Whether you're using flux or redux architecture, actions can be triggered from any part of the app, and perform changes in the global state, this changes will be reflected on any component that is listening to this state.
https://reactjs.org/blog/2014/07/30/flux-actions-and-the-dispatcher.html
https://redux.js.org/basics/actions

Reactjs - am I obligated to pass my nested components in a div box to trigger a function?

I'm working with ReactJS. I have a nested component as follow :
my componentParent.js :
import ComponentA {...}
<div {some properties}>
<div
{some properties}>
</div>
<ComponentA/>
</div>
my componentA.js :
import ComponentB {...}
foo.map{..} return (
<div onClick={this.onClick}>
<ComponentB/>
</div>)
on the componentA.js if I display directly the Component B and place the onClick method inside as :
import ComponentB {...}
foo.map{..} return (
<ComponentB onClick={this.onClick}/>
)
The method refuses to trigger on ComponentB in the second case. Am I always obligated to nest my component in a Div in order to trigger a function or existing a way to onClick directly on componentB ?
Any hint would be great,
Thanks.
When you pass 'onClick' to a component, it's a prop. When you assign it to plain old HTML element ("POHE"), React converts it to an event handler. Somewhere you need to assign it to an "POHE"
With your second version of ComponentA:
import ComponentB {...}
foo.map{..} return <ComponentB onClick={this.onClick}/>
If you modify <ComponentB> to call onClick={this.props.onClick} on a div or something, you'll see this is so.
Here's a JSFiddle example:
class Hello extends React.Component {
render() {
return <div onClick={this.props.onClick}>Hello {this.props.name}</div>;
}
}
function blah() {
console.log('sdfsdf');
}
ReactDOM.render(
<Hello name="World" onClick={blah}/>,
document.getElementById('container')
);

Why won't my nested React components render?

I'm having a problem with my React component. The nested children of my component ControlPanel don't seem to be rendering. Here is my code:
class App extends Component {
render() {
return (
<div className="App">
<ControlPanel>
<CustomerDisplay />
</ControlPanel>
</div>
);
}
}
I have the following two lines at the top of this file:
import ControlPanel from './components/control_panel';
import CustomerDisplay from './components/customer_display';
And here is my ControlPanel Component:
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './styles.scss';
const ControlPanel = () => {
return (
<div className="control_panel" id="control_panel">
</div>
);
}
export default CSSModules(ControlPanel, styles);
I have tried:
Calling the component as a full HTML tag (opening & closing)
Nesting the CustomerDisplay component in the ControlPanel component (in the ControlPanel's index.jsx file)
I know that nesting component's is possible. I've seen it done. For some reason it just won't work for me.
To allow components to contain children and render them correctly, you have to use this.props.children. This is passed to all components with children as a prop and contains the children of the component, as explained by the React documentation:
Containment
Some components don't know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic "boxes".
We recommend that such components use the special children prop to pass children elements directly into their output:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
This lets other components pass arbitrary children to them by nesting the JSX
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
As described in the documentation, some components don't know their children ahead of time -- they may be generic wrappers or boxes of content that vary, which is what your ControlPanel is. So, to render the children of your component, you must render the children from the children prop explicitly in the parent's render method. Thus, apply it like this to your code:
const ControlPanel = (props) => {
return (
<div className="control_panel" id="control_panel">
{props.children}
</div>
);
}
Notice how props.children is rendered (not this.props.children because it is a function component).
You can access the nested elements through props. So in your case do this:
const ControlPanel = (props) => {
return (
<div className="control_panel" id="control_panel">
{props.children}
</div>
);
}
You need to render the children in ControlPanel
const ControlPanel = ({ children }) => {
return (
<div className="control_panel" id="control_panel">
{children}
</div>
);
}
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
export default function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
Anything inside the<FancyBorder>JSX tag gets passed into the FancyBorder component as childrenprop. Since FancyBorder renders {props.children} inside a <div>, the passed elements appear in the final output.
This is what I was looking after, check it out here
https://reactjs.org/docs/composition-vs-inheritance.html
Your App.js (I understand that it is your JSX Index) should be:
import React from 'react';
import ReactDOM from 'react-dom';
export default class App extends Component {
render() {
return (
<div className="App">
<ControlPanel>
<CustomerDisplay />
</ControlPanel>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('YOUR_ROOT_ID'));
Try to add export default before class (in all your components).

How can I call a component's method from another component in React?

I have a modal component with two methods that show/hide the modal. How can I call those methods from another component?
This is the code for the Modal:
// Dependencies
//==============================================================================
import React from 'react'
import Modal from 'boron/DropModal'
// Class definition
//==============================================================================
export default class RegistrationModal extends React.Component {
showRegistrationModal() {
this.refs.registrationModal.show()
}
hideRegistrationModal() {
this.refs.registrationModal.hide()
}
render() {
return (
<Modal ref="registrationModal" className="modal">
<h2>Meld je aan</h2>
<button onClick={this.hideRegistrationModal.bind(this)}>Close</button>
</Modal>
)
}
}
You can call a components method from the outside as long as you keep a reference to the component. For example:
let myRegistrationModal = ReactDOM.render(<RegistrationModal />, approot );
// now you can call the method:
myRegistrationModal.showRegistrationModal()
It's a bit cleaner if you pass a reference to the modal to another component, like a button:
let OpenModalButton = props => (
<button onClick={ props.modal.showRegistrationModal }>{ props.children }</button>
);
let myRegistrationModal = ReactDOM.render(<RegistrationModal />, modalContainer );
ReactDOM.render(<OpenModalButton modal={ myRegistrationModal }>Click to open</OpenModalButton>, buttonContainer );
Working example: http://jsfiddle.net/69z2wepo/48169/
You cant call it from another component, because its a method belong to RegistrationModal component, but you can refactor your code so you can call it
export function hideRegistrationModal() {
console.log("ok");
}
export default class RegistrationModal extends React.Component {
render() {
return (
<Modal ref="registrationModal" className="modal">
<h2>Meld je aan</h2>
<button onClick={hideRegistrationModal}>Close</button>
</Modal>
)
}
}
now you can call from anywhere but you need to import it first like this
import { RegistrationModal, hideRegistrationModal } from 'path to modal.js'
// ^-- Component name ^-- Method
What you want to do is create a parent component which will handle the communication between your modals.
A really great example and explanation can be found here: ReactJS Two components communicating
This is a good approach because it keeps your components decoupled.

Categories