Ref and State difference in ReactJS - reactjs

https://facebook.github.io/react/docs/more-about-refs.html
Here i got idea about ref in React JS. But still not clear why ref is being used instead of State.

Refs are normally used to access DOM elements generally to set or get the html properties such as Width, Height etc. You can also use it to get the value e.g from a text field. States define the properties of a component that can change by different actions you perform.

Just to give you an example. Suppose you want to integrate Material Design Lite (MDL) into your React app. In order to properly hook MDL into a React component, it needs to have direct access to the underlying DOM element. That might be a valid use case for using refs.
import React from 'react';
class Button extends React.Component {
componentDidMount() {
window.componentHandler.upgradeElement(this.node);
}
componentWillUnmount() {
window.componentHandler.downgradeElements(this.node);
}
render() {
return (
<button
ref={node => { this.node = node; }}
className="mdl-button mdl-js-button mdl-js-ripple-effect"
>
{this.props.children}
</button>
);
}
}
export default Button;

Related

Get a reference to an element in React for using 'fromEvent' method of rxjs

In a React project that uses rxjs, I need to get a reference to an HTML element. I am using React.createRef:
const buttonWait = React.createRef();
<button ref={buttonWait}> Wait </button>
But { current: null } is printed to the console. How to get a link to an element to add to fromEvent and subscribe?
According to React's documentation on refs, React.createRef() is not to be used in functional components:
You may not use the ref attribute on function components because they don’t have instances.
Consider using useRef() instead:
import { useRef } from "react";
const buttonWait = useRef(null);
<button ref={buttonWait}> Wait </button>

Giving React component animation on mount

I am trying to make this component move in when mounted but getting
Cannot read property 'enter' of undefined
Here is a simplified code (I have all the CSS classes ready):
class Example extends React.Component {
state = {
transitionIn: false,
};
componentDidMount = () => {
this.setState({ transitionIn: true })
}
render() {
return (
<CSSTransition
in={this.state.transitionIn}
timeout={1000}
className={'wordTransition'}
>
<div>dksjfnsdkjnfj</div>
</CSSTransition>
);
}
}
https://codesandbox.io/s/rj5046zxoo
I believe that the error you were experiencing is one that you solved in the codesandbox.io link you provided above. I was having this same problem. Instead of naming the prop that takes a class name to be used as the prefix for the various transition states classNames (plural) I was using the more familiar className (singular).
To reiterate: inside the <CSSTransition> component, make sure you are using a classNames prop and not className as you would inside of a react component's html elements.
I feel that the choice on the part of the React Transition Group to use a prop called classNames in their component is confusing and should perhaps be reconsidered.

How to change state of component from anywhere without Redux?

Is this bad practices or not ?
export state change function from component
import it from other file.
call the function to change state?
In this way we can change some component state from anywhere.
For example...
We want to change the Model.js state from anywhere.
Modal.js
import React from 'react';
export let toggleModal;
export default class Modal extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false,
};
toggleModal = this.toggleModal;
}
toggleModal = () => {
this.setState({ open: !this.state.open });
};
render() {
const { open } = this.state;
return <div style={{ color: 'red' }}>{open && 'Hello Modal'}</div>;
}
}
App.js(Some Top Level component)
import React from 'react';
import Modal from './Modal';
export default () => (
<>
...
<Modal />
...
</>
);
Somewhere.js
import React from 'react';
import {toggleModal} from './Modal';
export default () => (
<>
<h1>Hello!</h1>
<button onClick={() => toggleModal()}>open Modal!</button>
</>
);
  
But there is no reference in React Official docs, so is this bad practices ?
What React Docs recommends...
Just passing function props to change parent state from parent to children
Use context
Redux or Mobx
But, these are too complex for me.
Example code here
https://next.plnkr.co/edit/37nutSDTWp8GGv2r?preview
Everything seems pretty much overwhelming and difficult at the beginning. But as we get out hands on them, it's give us more confidence to dig into.
I would recommend to use redux that's how we tackled props drilling problem. You can dispatch a action and connect reducer to corresponding component which upon updating state will re render. This is what I recommend to most of the people to learn the tale of redux with a real life example:
Understanding Redux: The World’s Easiest Guide to Beginning Redux
Apart from this you can take Dan Abramov, author of the library, free redux course on egghead.io:
Getting Started with Redux
The problem you run into, almost immediately like your code example does is this:
It will not work: your toggleModal() method expects a this to refer to an actual component instance. When your onClick() handler fires you invoke toggleModal() as a plain function. The this context will be wrong, and so at best (in your example) you will get an error because you try to invoke something undefined, at worst (in general) you end up invoking the wrong method.
When you think about it, for any non-trivial React component you will have a hard time obtaining a reference to the actual instance that is currently being used: you have to make sure that you are not forgetting to invoke the method on the right component instance and also you have to consider that instances may be created/destroyed 'at will' for whatever reason. For example: what if your component is rendered indirectly as part of some other component's render() method? Multiple layers of indirection like that make it even harder.
Now, you could fix all that by abusing ref with abandon but you will find that now you have to keep track of which ref refers to what particular instance, if you happen to have multiple of the components to consider in one render tree...
Whenever you think one component needs to handle the state of its siblings, the solution is usually to lift the state one level up.
export default class Modal extends React.Component {
render() {
const { isOpen } = this.props;
return <div style={{ color: 'red' }}>{isOpen && 'Hello Modal'}</div>;
}
}
export default class Home {
this.state = {
isOpen: false,
};
toggleModal = () => {
this.setState({ isOpen: !this.state.isOpen });
}
render() {
const { isOpen } = this.state;
return (
<>
<h1>Hello {name}!</h1>
<button onClick={() => this.toggleModal()}>open Modal!</button>
<Modal isOpen={isOpen}/>
<p>Start editing and see your changes reflected here immediately!</p>
</>
)
}
}
This way the Home handle the state and your problem is solved.
This can get annoying if the state needs to be "drilled down" to children, that's a problem than redux or react-context can solve.
Here <Modal /> is the child component. So to call a function in a child component you can simply use Ref.
You can refer this page to get more info about Ref.
You can assign a class variable as a ref to this child and use this class variable as an object to call its function.
I found if in special case, my way is okay.
Special case means something like customAlert component.
It is okay only one instance of customAlert component mounted at a time in App.
To achieve this...
1.Use ref to access and change DOM
2.attach state changing function or component to window and call window.function
3.my case: export state changing function and import it from other file.
And here is how to do with react Context
https://next.plnkr.co/edit/EpLm1Bq3ASiWECoE?preview
I think Redux is overkill if the main thing you are interested in is to make some states-like data available and updatable throughout your App without props drilling.
For that purpose, a much simpler approach (maybe not available at the time the question was posted?) is to use react context: https://frontend.turing.edu/lessons/module-3/advanced-react-hooks.html
"context - an API given to us by React, allowing for the passing of
information to child components without the use of props
[...]
useContext - a react hook, allowing functional components to take
advantage of the context API"

React: How do I access a component from another component?

I'm working on a project using react and I have a sign up modal and a login modal that are both separate components and I want to have two links ate the top of each modal to be able to switch from the sign up model to the login model. Each component model has a function open that looks like this:
open() {
this.setState({ showModal: true });
}
Is there a way for a component to call a function and set States from another component or do I need to make both models one component somehow?
The best way to handle communication between components is through a state container for the application that all components "hook in to".
Here's a very simple illustration:
// this state is defined somewhere in your application
// all of your components "hook in to" this state by including
// the values you want as props. For example,
// <MyFancyComponent value={state.value1} />
// and now MyFancyComponent has access to value1
state = {
value1: 42,
showModal1: false,
showModal2: false,
};
// somewhere in your application, there's a render method
// that looks like this
render() {
return (
<div>
{this.props.showModal1 ? <Modal1 /> : null}
{this.props.showModal2 ? <Modal2 /> : null}
{/* now render the rest of your component */}
</div>
);
}
The basic idea is that when this component (the one with the render method above) needs to show Modal1 or Modal2, it changes the appropriate flag in the state, which are mapped to the showModal* props on the component. Then the component re-renders and includes the appropriate modal. If you want to trigger a modal from another component, you change the appropriate flag in your application state & React will go to work re-rendering and show the modal.
The example above is ridiculously incomplete - it's intended to illustrate the basic idea only. To make this work, you'll need to implement a state container for your application. For that, I'd recommend either the flux pattern or redux.
Now, you could implement this as a set of callbacks & properties that are specific to the components you're working with, but I recommend against that - it becomes very difficult to manage, very quickly. Plus, it does not scale - to add a component, you would have to "wire it up" to all your other components manually.
In the component where you are rendering each of these login modals, you would want to pass in values through the props of each component. In the modal components, you would then use the value of the property passed in to determine if the modal should be shown.
Here's a quick example of how it could work (theoretically -- haven't tested):
Login/Signup Modal
import React from 'react';
const LoginModal = React.createClass({
propTypes: {
isVisible: React.PropTypes.boolean.isRequired,
onLogin: React.PropTypes.function,
},
componentWillReceiveProps(nextProps) {
// Will allow parent components to pass in a boolean
// telling this component when to render
this.setState({
showModal: nextProps.isVisible,
});
},
onSubmit() {
// TODO: Handle login
// If we let the parent handle the visibility, we just call
// the onLogin callback passed in and don't set this.state.showModal
this.props.onLogin();
},
render() {
return (
// Use this.state.showModal boolean to show/hide
// your login modal
);
},
});
export default LoginModal;
Parent Component
import React from 'react';
import LoginModal from './LoginModal';
const ParentComponent = React.createClass({
showLoginModal() {
this.setState({
showLogin: true,
});
},
hideLoginModal() {
this.setState({
showLogin: false,
});
// TODO: Likely change the route or do something else here...
},
render() {
return (
<button onClick={this.showLoginModal}>Login</button>
<LoginModal isVisible={this.state.showLogin} onLogin={this.hideLoginModal} />
);
},
});

How do I call the iScroll refresh methode in a parent react component?

I am struggling currenlty with iScroll in combination with reactJS.
This code samples are written in typescript.
I created a wrapper class for iScroll:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
var iScroll = require('iscroll');
...
componentDidMount() {
this._initializeIScrollInstance();
console.log(this);
}
_initializeIScrollInstance() {
setTimeout(() => {
let element = ReactDOM.findDOMNode(this);
const iScrollInstance = new iScroll(element, this.props.options);
this._iScrollInstance = iScrollInstance;
}, 100);
}
render() {
return (
<div style={ this.props.style } >
{ this.props.children }
</div>
)
}
}
Then I use it like this in my sidebar class for instance.
<ScrollWrapper>
<SidebarMenu toggle={ this.toggle.bind(this) } />
</ScrollWrapper>
The problem I am facing is when I toggle a menu inside my sidebar. This means the height changes so I need to call the refresh methode for iScroll.
But how can I achieve this?
Can I get the _iScrollInstance in my parent component?
Its possible to keep a state inside my sidebar and pass it down to the ScrollWrapper as a property and watch for it in componentReceiveProps.
But this sounds like a cheap solution to me.
Anyone maybe have a better solution for that kind of problem?
Based on your code :
<ScrollWrapper>
<SidebarMenu toggle={ this.toggle.bind(this) } />
</ScrollWrapper>
I see the child component action (toggle) needs to do something with the parent component (scroll). The idiomatic way to do this is for the parent to give the child component a function (callback) that the child calls when it wants something in the parent to change.
Note: The recommeded way is to use flux ... but thats a whole other topic (lookup redux which is what I use).

Resources