I was fetching data using onclick button but now i wanna fetch on page load using componentDidMount().
My fetch function is under action file and i am using react native with redux.
My function name is submitToServer(){}. How can i call it on componentDidMount?
Can anyone help me?
import React from 'react';
class SomeComponent extends React.Component {
componentDidMount() {
// here you fetch your data
submitToServer();
}
render() {
// ...
}
}
The submitToServer() call will then trigger some Redux store changes, which the react-redux library will process and trigger a properties change event in your SomeComponent component (if connected, of course). Then, your component will be re-rendered, and you would be able to use the retreived data.
Related
I wrote a component Foo in React.js (its parameter "interface" consists of a single parameter text; there are more parameters in my real code):
import React from 'react';
export default class Foo extends React.Component {
constructor(props){
super(props);
}
render(){
return <div>{this.props.text}</div>;
}
}
and I thought I could improve the code by modifying the property access as:
import React from 'react';
export default class Foo extends React.Component {
constructor(props){
super(props)
this._text = props.text
}
render(){
return <div>{this._text}</div>;
}
}
This would give me the benefits that
I can immediately see what properties are supported by having a look at the constructor.
The code that applies the properties gets shorter/better to read.
However, this destroys the update workflow for the property. In a parent component I use Foo like
<Foo text={this.state.parentText}/>
and
this.setState({parentText: "new text"})
does not trigger an update of the text in Foo any more. The constructor of Foo is only called once and therefore, the private variable this._text is not updated on property changes.
=> Using extra private properties to modify the parameter access turned out to be a bad idea.
=> What would you recommend to have a clear interface for the component without breaking the update workflow?
Some ideas:
a) List all used properties at the start of render (and componentDidUpdate)
render(){
const text = this.props.text;
return <div>{text}</div>;
}
b) Create a getter for each property and put them directly under the constructor, for example
get _text(){
return this.props.text;
}
c) (Only for shorter access.) Try to avoid class components. With function components there is direct access with props.text instead of this.props.text. Or, as a workaround, inherit from a custom component class that passes props argument to render:
render_props(props){
...
}
(Why doesn't react pass this.props as an argument to render by default?)
d) Document the supported properties in a doc string
=> If you know a better option / some standard / best practice, please let me know.
Also tried but failed:
I tried to use state in the child component, with the hope that it would be automatically updated on updates of the parent state:
import React from 'react';
export default class Foo extends React.Component {
constructor(props){
super(props)
this.state = {
text: props.text
}
}
render(){
return <div>{this.state.text}</div>;
}
}
However, this also breaks the update workflow. Using this.state only seems to make sense in the parent component.
Related:
Can I update a component's props in React.js?
https://github.com/vasanthk/react-bits/blob/master/anti-patterns/01.props-in-initial-state.md
Related topic:
How to interact with third party libraries using function components?
https://reactjs.org/docs/integrating-with-other-libraries.html
How do I use/include third party libraries in react?
Integrating React with Other Libraries
Use function components for React >= 16.8, also see recommendation at
https://www.w3schools.com/react/react_class.asp
Use useState hooks instead of setState. This is the modern way to write React, and gives you a simpler way to access state (foo.text, foo.setText). https://reactjs.org/docs/hooks-state.html
Typescript would help with docs (type props = { text: string }), but I also would like the answer for d) (your question is several questions I think).
Use props.text directly, instead of using extra shortcut variable const text = props.text suggested by option a). This way, you don't have a list of all available properties on top of the component function. However, using a consistent props. prefix makes it easier to spot the injected variables in the react code. If there is a huge number of properties and its hard to identify them, try to improve modularization.
JavaScript example code:
Child component Foo:
import React from 'react';
export default function Foo(props){
return <div>{props.text}</div>;
}
}
Parent component:
import React, { useState } from 'react';
import Froo from './foo';
export default function Parent(){
const [parentText, setParentText] = useState('Hello world');
return <Foo text={parentText}/>;
}
Have a ReactJS + Redux + Saga application that was recently updated to use the latest (or close to latest) versions of the respective JS libraries. After the library updates (no code changes) and running the application, I immediately see the "Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state." warning message in the console. It looks to be triggered by redux when I invoke the dispatch function (which then calls a function in Provider.js, then goes through react-dom, and then in turn writes the warning message. Again nothing in my code has changed, and my code is essentially built using stateless functions.
Not sure how to go about figuring out what is causing this warning-- although the app still runs ok as expected. Using React 16.8.6, react-redux 6.0.1, react-router-dom 5.0.0, redux 4.0.1, redux-saga 1.0.2, and connected-react-router 6.4.0.
Below is a sample page that would cause the warning message:
import React from 'react'
import {connect} from 'react-redux'
import {links} from '../links'
import {notify} from '../notifications'
const Home = props => {
const {dispatch} = props
return (
<main>
<p>
Go to Details...
</p>
</main>
)}
const dispatcher = dispatch => {
dispatch(notify(links.HOME))
return {dispatch}
}
export default connect(null, dispatcher)(Home)
You cannot call to dispatch inside the disaptcher function.
react-redux's connect parameters are:
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
mapDispatchToProps is what you called dispatch. These params are eventually run as functions that called in the render loop of the connected component. When you dispatch in the render loop it changes the state of a React component (looks like it's the Provider), which is forbidden by React.
Solution
Move the dispatch(notify(links.HOME)) to lifecycle method. For example you can add to the Home component (this will require to rewrite the Home component as an extension of React.Component class:
componentDidMount() {
dispatch(notify(links.HOME))
}
UPDATE
If you want to do this with classless component see that question
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.
Over on this question, it is answered how to bind a component to browser resize events. I'd like to create an HOC/decorator function to elegantly add this behaviour to Components in my Component Library so that I can be dry about adding this behaviour.
I was able to use the inverted HOC pattern to create a higher-order-component that will essentially attach the base components onResize method to a (resize) event listener:
import React from 'react';
import debounce from 'debounce';
import getDisplayName from 'recompose/getDisplayName'
export const withOnResize = BaseComponent => (
class ResizeEnhanced extends BaseComponent {
static displayName = getDisplayName(BaseComponent);
componentWillMount() {
this.debounce = debounce(this.onResize, 200);
window.addEventListener('resize', this.debounce);
if (super.componentWillMount) super.componentWillMount();
}
componentWillUnmount() {
window.removeEventListener('resize', this.debounce);
if (super.componentWillUnmount) super.componentWillUnmount();
}
render() {
return super.render();
}
}
);
and then the usage in some other component file:
export default withOnResize(MyComponent); // MyComponent has an onResize method.
--
This is sub-optimal at least because there is a dodgy reliance on the base component having an onResize method.
Is there a functional approach that would allow easily connecting resize listener and lifecycle events to a method on base components?
Obviously another option is to use something like Redux, and build the global events into the store - dispatching as required. Or even context if I was willing to re-render my entire app on context change, but I'm more interested in doing this at the component decoration level at this stage.
I do not want to call store.subscribe method. I just want to sync the store state with the component's state.
I am trying to make a shopping cart
- There is a component CartItems that displays SignleCartItem by passing props to SingleCartItem component using map function.
Whenever user updates the quantity SignleCartItem dispatches an action and store saves the total items added to the cart and their price.
Now the problem is that the component that displays SubTotal and Total of the cart items do not sync the state of the store with the its state ( which displays total ).
Making it simple:
One component updates the store state, other component is not syncing
it on run time.
PS: Please ignore the product detail :P
If I understand you correctly, you want to show store state 'total' in your component. You need to connect your component to the store.
An example in es6:
class SomeComponent extends React.Component{ ... }
const mapStateToProps = state => ({total:state.total});
export default connect(mapStateToProps)(SomeComponent);
doc about redux connect function is here:
https://github.com/reactjs/react-redux/blob/master/docs/api.md
If you want to keep track of changes made in redux store, like you said in your title, you can try redux-logger. You will be able to see, in your google chrome console, every action created and every changes in your store, like this
Instead of store.subscribe() use react-redux to bind Redux with React.
In your root component, import the store you created with createStore() and provide it to a component using Provider
import App from './App.js'
import store from './store/index.js'
import {Provider} from 'react-redux'
const myApp = () => (
<Provider store={store}>
<App />
</Provider>
);
ReactDOM.render(<myApp />, document.getElementById("root"));
Then, inside any component you want to listen to the state, use connect to connect the parts of state you want in that component by mapping them to the props
import {connect} from 'redux-react'
class App extends React.Component {
render(){
return (
<div>
<h1>{this.props.title}</h1>
<div>
)
}
}
Map the state to the props before you export the component
const mapStateToProps = (state) => {
title: state.title
}
export default connect(mapStateToProps)(App)