How can i declarate componentDidMount without creating class extends react component? For example render() declarates with react-dom package, maybe is exist another package for componentDidMount?
class App extends Component {
constructor(){
// do something
}
componentDidMount(){
// js code must run after page loaded
}
render(){
return(
<div className="app">
</div>
);
}
}
export {App};
The same thing with component constructor()
const App = () => {
// constructor and componentDidMount does not work here
// js code must run after page loaded
return (
<div className="app">
</div>
);
};
export {App};
First of all, what you want to achieve is fully Meteor independent. It's a pure React problem that could exist with any backend. What you want to achieve can be done using the useEffect() hook for which you'll find the documentation right here:
https://reactjs.org/docs/hooks-reference.html#useeffect
Here is a great article explaining how to replace lifecycle methods with hooks:
https://dev.to/trentyang/replace-lifecycle-with-hooks-in-react-3d4n
In your case, for componentDidMount you'll have to do the following:
useEffect(() => {
// js code must run after page loaded
}, []);
In the final array you have to put dependency that will retrigger the hook if you need. To imitate a simple componentDidMount an empty array is generally the solution.
Related
ReactJS is a great library, However, it misses some features which I found in Vue and Angular. These features can be implemented of course in React, however, they require extra code to be written.
Every react component, or every JSX element I should say has the following properties shared, which are given by React to us to consume:
ref
key
I wanted to add extra props:
renderIf
fallback
These props help in a way I can't describe when it comes to conditional rendering and filtering the views based on the logged-in user permissions and roles (and other conditional rendering use cases, of course).
In react, if we wanted to apply these props to our components, we would use a HOC as follows:
// 🍎 Disclaimer: you don't have to understand any of the code written bellow, the general idea is that this is a HOC.
import React from 'react'
import getVal from './getVal'
export default function EnhancedComponent(OriginalComponent) {
return ({ renderIf: renderIf_ = true, override: override_, fallback: fallback_ = undefined, ...props }) => {
const renderIf = getVal(renderIf_)
const override = getVal(override_)
const fallback = getVal(fallback_)
const consumersComponent = <OriginalComponent {...props} />
let render = fallback
if (renderIf) render = consumersComponent
if (override_ !== undefined) render = override
return render
}
}
Where every time you want to apply these props to your components, you would have to wrap every new component you create with EnhancedComponent as follows:
export default EnhancedComponent(function Sidenav(){
return <div> side nav </div>
})
Now, you can use your Sidenav component within your App component as follows:
import Sidenav from './Sidenav'
export default function App(){
return (
<div>
<Sidenav renderIf={(5 + 5 === 10)}/>
<div>etc</div>
</div>
)
}
This API is great, but it has a drawback, which is, every time you want to apply these cool props (renderIf and fallback) you'll have to repeat these steps:
import Enhanced component to your file.
wrap your export with Enhanced component.
What I am looking for, is a method, or a way to inherit, or to add some props to the original react component class, somehow?
In react class components, I can imagine doing this on the React.Component class which we used to extend from in the past
class Car extends React.Component{
constructor(){}
render(){
return <div>I miss you 🌹</div>
}
}
But in react functional component, how can we do that?
I want to apply these props by default everytime I create a new component, without wrapping my components in a HOC everytime.
Does React have a way to do that? To change its defaults ?
I am migrating my AngularJS website into ReactJS. I am new to React , so I am not much known to the background details of it. I have some classes that extends Injectables. But as React does not have dependency injections, how to treat them in React. I have some lines of code in AngularJS and want to convert it in ReactJS. What will be the strategy to do it?
class myClass extends Injectable {
$fetch(entities, resolveExtraContexts) {
const { $uibResolve, $q } = this.getServices(['$uibResolve', '$q']);
...
});
}
}
const fetcher = new myClass();
...
export default abc;
Here I do not know how to pass promises instead of $q . Also, what is the replacement of classes that extends Injectable. Last, but not the least, this.getServices just queues up all the dependency injection.
You may use componentDidMount and apply your api service logic there:
componentDidMount() {
// ... fetch
this.setState({fetchedData })
Now, strict to your question.
React has no dependency injection concept. And you may find this medium blog helpful.
If you want to apply injection logic in react, then you may use HOC. And you may find this medium blog helpful. The following code extracted from the linked blog:
function withApiService (WrappedComponent) {
class HOC extends React.Component {
render () {
const key = this.props.apiKey;
const apiService = new ApiService({key});
return (
<WrappedComponent
{...this.props}
apiService={apiService}
/>
);
}
}
return HOC;
}
The link for the code is : https://gist.github.com/justgoof9/b0ff1033cc83edeb72c687da0de4f89f
The problem with this is that It keeps on searching it and it never stops. How do I make it so that after the first search it stops?
As per your code here https://gist.github.com/justgoof9/b0ff1033cc83edeb72c687da0de4f89f
you are doing search in render and while you setState your render is being called again so this is causing infinite search so move that code to lifecycle method like componentWillMount or componentDidMount like this:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
const API_KEY = "9f64caf0";
class App extends Component {
constructor(props){
super(props);
this.state={
movies:[],
}
}
componentDidMount(){
const imdb = require("imdb-api");
imdb
.search({ title: "Game Of Thrones" }, { apiKey: API_KEY })
.then((movies)=>{this.setState({movies})})
console.log(this.state.movies)
}
render() {
return (
<div >
</div>
);
}
}
export default App;
You should use componentDidMount commit lifecycle hook for api calls not render or even componentWillMount
From React documentation - https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data
I am Quoting specific lines from the above page.
There is a common misconception that fetching in componentWillMount lets you avoid the first empty rendering state. In practice this was never true because React has always executed render immediately after componentWillMount. If the data is not available by the time componentWillMount fires, the first render will still show a loading state regardless of where you initiate the fetch. This is why moving the fetch to componentDidMount has no perceptible effect in the vast majority of cases.
I'm trying to create an automatic slideshow in react, using react-slideshow. I'm very new to react and have just begun. I got this code from here.
import React from 'react';
import { Fade } from 'react-slideshow-image';
const images = [
'./img/p1.png',
'./img/p1.png',
'./img/p1.png'
];
const Slideshow = () => {
return (
<Fade
images={images}
duration="5000"
transitionDuration="1000"/>
)
}
What I am not getting is how to make this slideshow actually render. What I have done is called this function from inside a component in the same file i.e.
class App extends Component {
render() {
return (
<div className="App">
{Slideshow();}
</div>
);
}
}
export default App;
This is not rendering any slideshow or image, about which I'm not too surprised. The function is running. I console logged something and it got logged on the console. The rest of the page (I have other divs not shown here) is rendered and there is no error thrown. How to make this work?
Nothing seems wrong in this code.
try defining Slideshow() function inside app component.
make a call like "{ this.Slideshow }".
Check by removing "./" in image path. (Try..)
Also check the path of image. Sometime they refer to public folder outside the src folder. maybe public/images/img.png
Slideshow is a React component, so you need to render it using JSX, not invoke the function:
class App extends Component {
render() {
return (
<div className="App">
<Slideshow/>
</div>
);
}
}
export default App;
I am using a component:- https://github.com/christianalfoni/formsy-react, for creating forms. I am trying to create one of my own components of the input. So as mentioned I need to use it for my's mixin. But unfortunately, there is no support for it in es6 style. So any work around anyone knows of.
here is my component code:-
import Formsy from 'formsy-react';
class DropDownAutoComplete extends React.Component {
constructor(props, context) {
super(props, context);
this.mixins = [Formsy.Mixin];
}
changeValue(event) {
this.mixins[0].setValue(event.currentTarget.value);
}
handleValue1Change(value) {
this.setState({value: value});
}
render() {
const className = this.mixins[0].showRequired() ? 'required' : this.mixins[0].showError() ? 'error' : null;
// An error message is returned ONLY if the component is invalid
// or the server has returned an error message
const errorMessage = this.mixins[0].getErrorMessage();
return <DropdownList
data={this.props.dropDownConfigs.value}
onChange={this.changeValue.bind(this)}
textField={this.props.dropDownConfigs.name}
caseSensitive={false}
filter='contains'>
</DropdownList>
}
}
It's throwing an error where the show required function is called. Apparently, its implementation uses some state variables like required.
By design, mixins do not work with ES6 classes - trying to hack something together is just going to cause you headaches!
One solution is to use what's called a higher-order component - a function that takes in a component, and returns a new component that wraps around it. These wrapper components can have lifecycle hooks of their own, and can pass props down to the wrapped components, effectively providing you with the same functionality mixins would give you, but arguably in a cleaner way!
formsy-react allows you to take this approach, providing its own HOC:
import {HOC} from 'formsy-react';
class MyInput extends React.Component {
render() {
return (
<div>
<input value={this.props.getValue()} onChange={(e) => this.props.setValue(e.target.value)}/>
</div>
);
}
};
export default HOC(MyInput);
You can use react-mixin-decorator.
Quoting from README:
If you're creating React components using ES6 classes and you'd like
to use existing mixins to add some nice functionality to your
component, you probably don't want to take the time to convert the
mixins to something that your ES6 React component class could use.