Categories
React Tips

React Tips — super, Call Child Methods, Debounce, and Inlint Styles

Spread the love

React is a popular library for creating web apps and mobile apps.

In this article, we’ll look at some tips for writing better React apps.

Difference Between “super()” and “super(props)” in React when Using ES6 Classes?

The only difference between the 2 is when we need to access props in the constructor.

If we need to get them in the constructor, then we’ve to get the props from the parameters and pass it into super .

For instance, we write:

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    console.log(this.props);
  }

  render(){
    //...
  }
}

If we don’t, then we can skip it:

class MyComponent extends React.Component {
  constructor(props) {
    super()
  }

  render(){
    //...
  }
}

Inline Style Best Practices

We can put inline styles by passing in an objecty with the styles or className prop.

For instance, we can write:

<li
 className={classnames({ 'list-item': true, 'is-complete': item.complete })} />

We used the classnames package to dynamically set the class names of the li element.

Also, we can write:

<li style={Object.assign({}, fooStyles, barStyles)}>

We just set the styles by passing in an object with all the style properties.

The keys have the attributes and the values are the values.

Does render Get Called Any Time “setState” is Called?

setState is called every time render is called.

This is why we can’t use setState in the render method.

Otherwise, we’ll get an infinite render loop.

If we don’t want it to be called on every setState call, we should have the shouldComponentUpdate hook.

We can compare the state and props and return a boolean expression with the condition to notify React when the component should render.

showComponentUpdate gas the following signature:

shouldComponentUpdate(nextProps, nextState)

Perform Debounce in React

We can denounce with React by using the awesome-debounce-promise package,

For instance, we can write:

const searchAPI = text => fetch(`/search?text=${encodeURIComponent(text)}`);

const searchAPIDebounced = AwesomeDebouncePromise(searchAPI, 500);

class SearchInputAndResults extends React.Component {
  state = {
    text: '',
    results: null,
  };

  search = async text => {
    this.setState({ text, results: null });
    const result = await searchAPIDebounced(text);
    this.setState({ result });
  };
  //...
}

We use the AwesomeDebouncePromise function to delay the searchAPI function by 500 ms.

Then in the sesrch method, we use the promise returned by the package and use setState to set the data.

We can also use it with function components.

For instance, we can write:

const searchAPI = text => fetch(`/search?text=${encodeURIComponent(text)}`);

const searchAPIDebounced = AwesomeDebouncePromise(searchAPI, 500);`

const App = () => {
  const [results, setResults] = useState([]);
  const [text, setText] = useState(['');`

  search = async text => {
    const result = await searchAPIDebounced(text);
    `setResults`(result);
  };

 return (
    <div>
      <input value={setText} onChange={e => setText(e.target.value)} />
      <div>
        {results && (
          <div>
            <ul>
              {results.map(r => (
                <li key={r.name}>{r.name}</li>
              ))}
            </ul>
          </div>
        )}
      </div>
    </div>
  );
};

We use the same function and the useState hook to set the state when it’s done.

This is all done in the search function.

Call Child Method from Parent

We can call a child method from a parent by forwarding the ref to the child.

Then we can get the child’s method from the ref.

For instance, we can write:

const Child = forwardRef((props, ref) => {
  useImperativeHandle(ref, () => ({
    hello() {
      console.log("hello Child");
    }
  }));

  return <h1>Hi</h1>;
});

const Parent = () => {
  const childRef = useRef();

  return (
    <div>
      <Child ref={childRef} />
      <button onClick={() => childRef.current.hello()}>Click</button>
    </div>
  );
};

We call forwardRef on the child with a callback that returns our component.

The useImperrativeHandle hook gets the ref and returns an object w8itht eh methods we want to call.

Then in the parent, we pass the ref to the ref prop.

Then we call current.hello to call the method in the child.

If we use class components, then it’s simpler.

For instance, we can write:

const { Component } = React;

class Parent extends Component {
  constructor(props) {
    super(props);
    this.child = React.createRef();
  }

  onClick = () => {
    this.child.current.hello();
  };

  render() {
    return (
      <div>
        <Child ref={this.child} />
        <button onClick={this.onClick}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  hello() {
    conole.log('hello child');
  }

  render() {
    return <h1>Hello</h1>;
  }
}

We create a Child with the hello method which we call from the Parent .

Then we just assign a ref to it and call it with current.hello .

Conclusion

We can call child component function from the parent.

If we need to access props in the constructor, then we need to pass them into super .

We can denounce event handlers with 3rd party libraries.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *