Just trying reactjs and came across the situation that I want to call a method on another component:
class MyComp extends React.Component {
callMe(){
...
}
}
So mycomp2:
import MyComp from 'myComp';
class MyComp2 extends React.Component {
test(){
MyComp.callMe();
}
}
How can I do this ?
If the method callMe doesn't use this, you can declear it as static to use it like that.
class MyComp extends React.Component {
static callMe(){
...
}
}
If not, you can use ref to make it work.
You may need:
https://facebook.github.io/react/docs/refs-and-the-dom.html
Cannot. You cannot do that in react component. The only way is to move that function to their common ancestor.
Of course, there is another way, why not consider redux? let's react component talk through redux state. that way, you will never have this puzzle.
It depends on how your components are related to one another. If one is a parent and the other is a child then the function can be passed as a prop from parent to child, e.g.
class Parent extends React.Component {
callMe() {
console.log('called');
}
render() {
return (
<Child doSomething={() => this.callMe()} />
);
}
}
class Child extends React.Component {
render() {
<button onClick={this.props.doSomething}>Calls the parent fn</button>
}
}
Alternatively if they are not a parent-child relationship, then you need to introduce a parent component in which the function can live, then pass it via props in the same way.
If neither of these approaches seems to fit, then let us know what behaviour you are trying to achieve that requires this, and there my well be a different way to structure your code.
Related
I am wondering what the effects of coupling / nesting a functional component inside a React class component without explicitly passing props to it via params and using this.props via the parent class are. I understand that having a functional component outside of the React class component is easier to test and read, but am curious to know what the exact difference between using this.props vs props via params are in terms of performance / renders.
For example:
class Foo extends React.Component {
bar = () => { return (<p>{this.props.baz}</p>) }
render() {
return (
<h1>Hello, {this.props.name}</h1>
{this.bar()}
)
}
}
Vs.
class Foo extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
<Bar baz={'foobar'}
)
}
}
function Bar(props) {
return <p>{props.baz}</p>
}
Both give the same result except when you care about code reusability.
If you care about reusing the Bar function then you better keep it outside the class so you can import it elsewhere.
Example:
If Bar renders a success or warning message. you'll want to keep the same design for all warning messages in the system.
Now if every component has its own warning message code, you'll not be able to edit the warning message design easily also you'll have to keep rewriting the same code over and over again.
I want to know the conditions where by a constructor is not needed in a component's class declaration. I figure it is for stateless components, but are there any other reasons? Would not having any functions inside the component (besides life cycle functions) be one, for example?
I think it would be appropriate to just leave here an excerpt from react docs (emphasis mine):
The constructor is the right place to initialize state. If you don't
initialize state and you don't bind methods, you don't need to
implement a constructor for your React component.
I usually only add a constructor if the component has a internal state I need to set up before it is used, otherwise I leave out the constructor. Having functions in the component doesn't affect my decision in this regard
You don't actually need a constructor at all in any case if you use the babel stage-2 preset, because it provides the class properties that effectively replace its usage:
class Component extends React.Component {
constructor() {
this.state = {};
this.handleClick = this.handleClick.bind(this);
}
handleClick() { console.log('click'); }
}
becomes
class Component extends React.Component {
state = {};
handleClick = () => console.log('click');
}
Ignoring this, a constructor is needed only if you need to bind component methods to its context, or if you need to initialize the state property.
Another case is if you need to do something with the this.props class property, but this is considered an anti-pattern by React.
class Component extends React.Component {
constructor() {
this.state = {
// don't do this! anti-pattern! duplication of source of truth!
duplicatedState: this.props.myName,
};
}
}
I'm using MaterialUI, more specifically the TextField component which I want to decorate somehow to handle validation state at a component level.
I know about the HOC in react, which is a pattern that seems to be perfect for this. But I have to return an anonymous class and therefore I cannot get the value of the TextField component as I should, because the type returned is _class instead of TextField.
Am I doing something wrong with the HOC pattern, or perhaps this is not the best way to reuse a component without modifying its prototype. Any help would be greatly appreciated.
The HOC declaration
export default function hocInputValidator( WrappedComponent ){
return class extends Component{
constructor(props){
super(props);
}
handleChange(){
console.log('Handling from HOC');
}
render(){
return <WrappedComponent {...this.props}/>
}
}
}
The invocation and exporting of the decorated component
export default hocInputValidator(TextField);
When I try to access the decorated component via refs, the type is _class instead of TextField.
HOCs are used mainly for cross cutting of concerns for an example Login. Many components in your app may require Login functionality, hence you can wrap them with an HOC dynamically. An HOC will merely wrap whatever the component that is passed into it. In your case I figured out few issues in your code. I have fixed them below.
export default function ( WrappedComponent ){
class HocInputValidator extends Component{
constructor(props){
super(props);
}
handleChange(){
console.log('Handling from HOC');
}
render(){
return <WrappedComponent {...this.props}/>
}
}
return HocInputValidator;
}
The invocation should be something like this.
import inputValidator from './components/input_validator';
inputvalidator(TextField);
Your HOC returns an anonymous class which is why it's being displayed as _class.
To work around this you can set the HOC's displayName to something descriptive which will override the _class display behaviour.
For instance, you can display the HOC as something like HigherOrderComponent(WrappedComponent) in the DOM which is more descriptive (and easier to debug). It's a convention followed by other libraries such as react-redux.
Im new to react and i was wondering how i can call a child components method from the parent?
for example
var ChildClass = class Child {
howDoICallThis () {
console.log('Called!')
}
render () {
return (<Text> Child Class </Text>)
}
}
var ParentClass = class Parent {
// how can i call child.howDoICallThis() ?
render () {
return (<ChildClass> </ChildClass>)
}
}
Can someone explain clearly how i can do this?
This isn't really how things should be done in React. One very common way of approaching these situations is to define methods within a container component that handles business logic, then pass those methods down to presentational components as props.
class Child extends Component {
render () {
return <Text onClick={this.props.handleClick}>Child Class</Text>
}
}
class Parent extends Component {
handleClick = () => {
console.log('Called!')
}
render () {
return <Child handleClick={this.handleClick} />
}
}
Basically, you're wanting to pass things up, where React is designed to pass things down. You can still pass things up using refs and 'lifting state up' (see https://facebook.github.io/react/docs/lifting-state-up.html), but as far as methods go, you should really only ever pass them down. If you structure your components correctly, you shouldn't ever have to call a child's method from the parent.
(btw... make sure you are extending Component. you missed this in you sample code)
The docs for React state that component functions can be accessed by a parent component via refs. See: https://facebook.github.io/react/tips/expose-component-functions.html
I am attempting to use this in my application but run into an "undefined is not a function" error when the child function is called. I'm wondering if this has anything to do with using the ES6 format for React classes because I don't see any other differences between my code and the docs.
I have a Dialog component that looks like the following pseudocode. The Dialog has a "Save" button that calls save(), which needs to call the save() function in the child Content component. The Content component collects information from child form fields and performs the save.
class MyDialog extends React.Component {
save() {
this.refs.content.save(); <-- save() is undefined
}
render() {
return (
<Dialog action={this.save.bind(this)}>
<Content ref="content"/>
</Dialog>);
}
}
class Content extends React.Component {
save() {
// Get values from child fields
// and save the content
}
}
I could instead pass a prop (saveOnNextUpdate) down to Content and then execute save whenever it is true, but I would rather figure out how to get the method detailed in the React doc above to work.
Any ideas on how to get the doc approach to work or access the child component function in a different way?
Redux connect accepts an option parametre as the forth parameter. In this option parameter you can set the flag withRef to true. Then you can access functions to refs by using getWrappedInstance(). Like this:
class MyDialog extends React.Component {
save() {
this.refs.content.getWrappedInstance().save();
}
render() {
return (
<Dialog action={this.save.bind(this)}>
<Content ref="content"/>
</Dialog>);
}
}
class Content extends React.Component {
save() { ... }
}
function mapStateToProps(state) { ... }
module.exports = connect(mapStateToProps, null, null, { withRef: true })(Content);
Read more about it here: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
Worth reading this article about use of refs and consider if there's better approaches: https://facebook.github.io/react/docs/refs-and-the-dom.html#dont-overuse-refs
An alternative way to do this would be to use some other prop name (other than ref). I've found that this also works well if you're using a library like styled-components or emotion For example in a connected MyComponent:
<MyComponent
...
innerRef={(node) => { this.myRef = node; }}
/>
As it turns out, m90 was right -- this was a different issue entirely. I'm posting the solution in case someone runs into the same problem in the future.
My application is built with Redux, and the problem stems from using the react-redux connect function to connect a component to the store/global state. For some reason, exporting a component and connecting it to the store makes it impossible to access the functions inside of it. In order to get around this, I had to remove all use of global state from Content so that I could export it as a "dumb" component.
To be more clear, Content.js looked like this:
var connect = require('react-redux').connect;
class Content extends React.Component {
save() {
// Get values from child fields
// and save the content
// Use of this.props.stateObject
}
}
function mapStateToProps(state) {
const {
stateObject
} = state;
return {
stateObject
};
}
module.exports = connect(mapStateToProps)(Content);
Removing the use of global state (and therefore the use of connect and mapStateToProps allowed me to export the component using:
module.exports = Content;
Accessing this.refs.content.save() magically worked after doing this.