How to pass ref by props in ReactJs? - reactjs

This is my components logic:
component_1
|
'------component_2
I have an input in component_2, and I want to put .focus () on it, but the function that will do this is in component_1, how can I do it?
And I think it will do the ref, if I'm wrong please correct me.

Since React 16.3, you can use React.createRef() in Component1 and pass it to the input via Component2 using ref forwarding:
const Component2 = React.forwardRef((props, ref) => (
<input ref={ref} />
));
class Component1 extends React.Component {
ref = React.createRef();
componentDidMount() {
setTimeout(() => this.ref.current.focus(), 1000);
}
render() {
return <Component2 ref={this.ref} />;
}
}
ReactDOM.render(
<Component1 />,
document.getElementById('demo')
);
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="demo"></div>

Related

Is there a way of passing props to class component?

I'm a beginner in React.
I still quite don't understand how to pass props to a class component like we do in a function.
Example of a function:
const SurveyFormReview = ({ onCancel, formValues, submitSurvey, history }) => {
return (
...
<button
onClick={() => submitSurvey(formValues, history)}
className="green btn-flat right white-text"
>
...
);
};
Example of a class Component:
class ImageUpload extends Component {
render() {
return (
// I want to use props in here
)
}
}
For example
<ImageUpload propExample="property" />
Inside ImageUpload component you can access it by writing:
this.props.propExample
Just use whatever attributes you want when using the ImageUpload component:
<ImageUpload propA="someValue" propB={someVariable}/>
From the ImageUpload component, just call the props property:
someFunction = () => {
var propAValue = this.props.propA;
var propBValue = this.props.propB;
}
That's it!
You can pass any value as a props in Class and functional components in react. Read more about props
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
};
ReactDOM.render(
<Welcome name="Sara" />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>

re-render only one child with react-hooks

const {useRef, useState} = React;
function List(){
const renderCount = useRef(0);
console.log('<List /> is rendered', ++renderCount.current);
const [isClicked, setIsClicked] = useState(false);
const toggle = () => setIsClicked(!isClicked)
return (
<div>
<ButtonA onClick={toggle} isClicked={isClicked} />
<ButtonB />
</div>
)
}
function ButtonA(props){
const renderCount = useRef(0);
console.log('<ButtonA /> is rendered', ++renderCount.current);
return (<button onClick={props.onClick} className={`${props.isClicked ? 'true':'false'}`} >Button A</button>);
}
function ButtonB(){
const renderCount = useRef(0);
console.log('<ButtonB /> is rendered', ++renderCount.current);
return (<button>Button B </button>);
}
ReactDOM.render(
<List />, document.getElementById('root')
)
button.true{
background-color: red;
}
button.false{
background-color: blue;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
It's a sample code.
When I clicked <ButtonA />, and I expected re-rendering <List /> and <Button A/>, but <ButtonB /> was also re-rendered.
I wanna block re-rendering <ButtonB /> when I click <ButtonA />
How can I achieve it?
You can make use of React.memo to have the same functionality as shouldComponentUpdate for functional component
const {useRef, useState} = React;
function List(){
const renderCount = useRef(0);
console.log('<List /> is rendered', ++renderCount.current);
const [isClicked, setIsClicked] = useState(false);
const toggle = () => setIsClicked(!isClicked)
return (
<div>
<ButtonA onClick={toggle} isClicked={isClicked} />
<ButtonB />
</div>
)
}
function ButtonA(props){
const renderCount = useRef(0);
console.log('<ButtonA /> is rendered', ++renderCount.current);
return (<button onClick={props.onClick} className={`${props.isClicked ? 'true':'false'}`} >Button A</button>);
}
const ButtonB = React.memo(() => {
const renderCount = useRef(0);
console.log('<ButtonB /> is rendered', ++renderCount.current);
return (<button>Button B </button>);
})
ReactDOM.render(
<List />, document.getElementById('root')
)
button.true{
background-color: red;
}
button.false{
background-color: blue;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
Optimizing a functional component so that React can treat it as a pure component shouldn’t necessarily require that the component be converted to a class component.
If you are already familiar with the recompose package then you know that it provides a wide collection of higher-order components that makes it very useful when dealing with functional components.
The recompose package exports a {pure} higher-order component that tries to optimize a React component by preventing updates on the component unless a prop has changed, using shallowEqual() to test for changes.
Using the pure higher-order component, our functional component can be wrapped as follows:
import React from 'react';
import { pure } from 'recompose';
function ButtonB() {
const renderCount = useRef(0);
console.log('<ButtonB /> is rendered', ++renderCount.current);
return (<button>Button B </button>);
}
// Wrap component using the `pure` HOC from recompose
export default pure(ButtonB);
By default all children of the parent is re-rendered if the parent's state changes. No matters if this change has a direct effect to the child or not.
However you can explicitly disable the re-render of a specific component using the shouldComponentUpdate lifecycle method.
class Button extends React.Component {
shouldComponentUpdate(){
return !this.props.shouldNotUpdate;
}
render(){
const { id, onClick } = this.props;
console.log(`button ${this.props.id} rendered`)
return <button onClick={onClick}>{`Button ${id}`}</button>
}
}
class App extends React.Component {
state = { clicked: 0 }
handleClick = () => this.setState(({clicked}) => ({clicked: clicked + 1}))
render(){
return (
<div>
{this.state.clicked}<br />
<Button id="1" onClick={this.handleClick} />
<Button id="2" shouldNotUpdate />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

how to use pure flatpickr in react?

I'm new in reactJS, and I am trying to use pure flatpickr (https://flatpickr.js.org , NOT react-flatpickr)
Below is my current code. Any help on how to implement it properly?
import React, { Component } from "react"
import flatpickr from "flatpickr"
export default class Datepicker extends Component<IProps> {
public render() {
flatpickr(".datepicker")
return (
<div>
<input type="text" className="datepicker" />
</div>
)
}
}
flatpickr requires a node or selector passed into it. In React, for referring to the DOM, we use a ref
For handling events and providing other options, you can use the second argument for options.
Here is a demo:
class App extends React.Component {
constructor(props) {
super(props);
this.datePicker = React.createRef();
}
onChange(selectedDates, dateStr, instance) {
console.log(selectedDates);
}
componentDidMount() {
flatpickr(this.datePicker.current, {
onChange: this.onChange
});
}
render() {
return(
<input type="date" ref={this.datePicker} />
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<div id="root"></div>
Example with hooks & Typescript (I had to use useCallback and useRef to make it work):
// Or configure the styling elsewhere.
import 'flatpickr/dist/flatpickr.css';
import flatpickr from 'flatpickr';
import { Instance } from 'flatpickr/dist/types/instance';
export default function Comp() {
const fp1 = useRef() as MutableRefObject<Instance>;
const inputRef = useCallback((node) => {
if (node !== null) {
fp1.current = flatpickr(node, {});
}
}, []);
return (<input type="date" ref={inputRef} />);
}

Automatically map the same props to multiple React components

I have multiple React components that will receive the same props...
...
render () {
const { someProps } = this.props
return (
<div className="someDiv">
<Component1 someProps={someProps}/>
<Component2 someProps={someProps}/>
</div>
)
}
...
The above code works fine but is there a more dynamic way of doing this? Mabye do a .map() over an array of Component names?
Array of components should work just fine.
const Component1 = (props) => <div>Component 1</div>
const Component2 = (props) => <div>Component 2</div>
const Component3 = (props) => <div>Component 3</div>
const components = [Component1, Component2, Component3]
class App extends React.Component {
render() {
const { someProps } = this.props
return (
<div>
<h3>Root component</h3>
{components.map((Component, index) =>
<Component key={index} someProps={someProps} />
)}
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Can we pass event name as props in react?

Hi I am new to react and I am trying to create a component where we can pass event name(onclick, onChange etc.) as props. So the component can be customize in an event way as well. Is it possible?
<Input {this.props.eventName} = {this.props.name} />
This I want to do. Is it possible?
Do you want to achieve something similar to this -
One problem is that you must pass only supported events to the element type.
e.g in case of button onClick and other events supported by button.
class Parent extends React.Component {
render() {
return(
<ChildComponent
evtName = 'onClick'
evtHandler={ () => { console.log("event called!");}}
/>
)
}
}
class ChildComponent extends React.Component {
render() {
return React.createElement(
'button',
{ [this.props.evtName] : this.props.evtHandler },
'Click me'
); }
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
If I understand you correctly, just pass the event and it's handler as props. I didn't see the use case just considering the event name.
See the below example of reusing the same element with different events.
class Input extends React.Component {
render(){
const {} = this.props;
return (
<input {...this.props} />
);
}
}
class Test extends React.Component {
render(){
return (
<div>
<Input name="onClick" onClick={(e) => console.log(e.target.name)}/>
<Input name="onChange" onChange={(e) => console.log(e.target.name)}/>
</div>
);
}
}
ReactDOM.render(<Test />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Here is example how to pass an event from parent Component to Child - by having result in Parent Component.
class Parent extends Component {
//constructor, other methods, etc...
// We call our event update
update(stuff) {
console.log(stuff);
}
}
We pass in ParentComponent's render method a ChildComponent with props onClick(you can name it whatever you want).
<ChildComponent
onClick={this.update.bind(this)}
/>
Now, ChildComponent. To access our props onClick, we just use this.props.onClick. Our argument is just hello, you can pass as many arguments you want.
<button onClick={ (e) => this.props.onClick('hello') }>
Action
</button>
Here is working example:
class Parent extends React.Component {
update(stuff) {
console.log(e, stuff);
}
render() {
return(
<ChildComponent
onClick={this.update.bind(this)} />
)
}
}
class ChildComponent extends React.Component {
render() {
return(
<div>
<button onClick={ (e) => this.props.onClick('hello') }> Action</button>
</div>
)
}
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Resources