React how to update the data in App.js from child component - javascript

I'm building a React App. I don't have a backend server. Instead, I used a .json file called securities.json as the backend server. The .json file list the securities and the price list in each security.
What I am attempting to do is to submit the updated price list to the securities.json on App.js, a parent component, from its child component. I noticed that when I add a new price in the Price Popup window and then close it but rechecked the Price Popup window again. The new price that I entered disappeared. I couldn't figure out how to solve it. I'm trying to pass it up to App.js as one developer suggested.
Can someone please take a look at my code in CodeSandBox?
https://codesandbox.io/s/github/kikidesignnet/caissa

Two solutions:
Use Redux: https://react-redux.js.org/
Use reacts context system: https://reactjs.org/docs/context.html
you can also pass an update function as props to your child component which updates the state of the parent.

My guess is price list is set in constructor. There the state is set from props. On change of props, the price list state is not updated as setting state happens in constructor which executed only once. You need to update state when ever props get changed.
This is the code I am talking about
constructor(props) {
super(props);
this.state = {
priceArr: this.props.pricelist,
// newPriceArr: this.props.updatePrice,
showPricePopup: false,
addPricePopup: false,
isToggleOn: true,
date: props.date || "",
number: props.number || ""
};
}
You may need to use getDerivedStateFromProps to set state when props change.

Related

React classes in main component constructor

Let's say I have a lot of app state to manage in my React application.
Therefore, I would like to split the state into smaller, manageable chunks.
For example I have the following main component with state and methods that alter this state.
class App extends Component {
constructor(props) {
super(props);
this.state = {
foo: ['some', 'items'],
bar: [{ arr: 'of objects'}]
}
}
changeFoo() {some code in here...}
changeBar() {some code in here...}
}
The state and methods written in the App component are getting out of hand. Yet it must be written in the App component since the state is passed to other components as props.
How would you usually manage this?
When you see that the state of your React application is getting out of hand, it's usually time to bring in a state management library like Redux (there're a few and Redux is the most popular one).
It'll help you have a global state that is managed in a reasonable way.
When we see how React works. It is based on one-directional data flow.
So, usually the Application state is kept at the top most Component (Say, App Component) in your case. So that data/state can be passed down as props to the component that needs it.
There, however may be the cases where children components of the parent, needs to work with the same data(Say in case of an event - a button click that happens in the child component.) In that case we write a function in the parent component and pass the function as props to the children, so that the state gets updated in the parent itself and any child gets updated data.
In pure React (without using any state management library), we have to pass the state as props to work with our app. But in case you choose to use a state management library such as Redux, then the components (known as Containers) can directly communicate with the Application State.
And If your application state contains objects within objects(like you have shown) or Array of Objects containing more Objects, then you cannot use setState() to update the state directly. In most of the cases, you take copy of the state and then use JSON.parse(JSON.stringify(state)) to do deep cloning and work with the state in a best possible manner.
There are other things in the example, the functions that you have used within the class , you need to bind the scope of this variable to point to the current class. This we do inside the constructor method, or simple make use of arrow function in order to avoid errors.
If you need more explanation, I will share with you :)
One solution is to make a generic change() function with a parameter for the key that should be changed:
change(key, value) {
setState({key: value, ...this.state});
}
Now when you want to add a listener to a child component:
<Foo onChange={ value => change('foo', value) }/>
<Bar onChange={ value => change('bar', value) }/>

How I should use shouldComponentUpdate here to update parent state in React.js?

I am new in React.js, and I have an issue with parent component state updating. I attached whole code so that don't miss something that can be important.
I need my 'Reset' button to reset parent component's state
HERE you can see what the issue is.
You should open 'Events' in Navigator menu and try to select categories and then to reset them.
parent component: components/events/filter-bar.js
chils component: components/shared/dropdown/category.js
So, you have categories in FilterBar and Category components state - which are not in sync. Since FilterBar also recieves categories as a prop - that indicates that you don't have a single source of truth for categories. There are at least three places where you are keeping categories in different components states. That is very bad thing and leads to bugs and hard to maintain state. Solution is having categories state in just one place and than passing it down to components which need them (together with methods for updating categories).
Anyway, if reseting only dropdown categories is what you want this is what you can do:
create a new method in FilterBar, name it whatewer you want and pass it as a prop to Categories component. This method will accept just one argument - array of categories. This method will update FilterBar state.categories.
in Categories component, remove state.selected and saveSelected method. In places where you are using saveSelected replace it with prop (function/method) passed from FilterBar.
update
This question actually has nothing to do with component lifecycles or updating parent state.
Here is a thing: you can't control the state you don't own (which is the case with 3rd party components). Some lib authors provide methods for setting initial state or reset, but that is not the case with component library you are using.
In your case, best you can do is to unmount dropdowns ad then mounts them again. It's something like refreshing just the part of the page.
Do this:
add visible: true to the FilterBar state
add onReset method to the same component:
onReset = () => {
this.setState(
state => ({ visible: false }),
() => {
this.setState({ visible: true });
}
);
};
update reset button: onClick={this.onReset}
conditionally render ButtonToolbar:
return this.state.visible ? <ButtonToolbar /> : null // have shortened code just for demonstration purpose

Is there a way to call a child-component's function from another child?

I'm contributing to an open-sourced React/Redux application built using ES6 JavaScript. I'm fairly new to React/Redux so I'm having some trouble.
I have a parent class that's rendering two different React components. The first component contains some input fields regarding events (called NewShift). The second component is a calendar that renders these events (called Index).
Once a user fills out the input fields and presses a button in the first component, I want to be able to re-render the calendar in the second component. If the re-render function is in the calendar component, how do I call it from the input fields component (both children).
React re-renders components whenever component state is changed. Should you be using just React, this would mean passing changed values up to the parent component's state to force a re-render.
However, Redux makes this easier on you, as it's 'Store' functions as a global state. You can force a re-render by changing appropriate variables within the store.
Given your situation: the button should get this within it's onClick attribute:
onClick={() => dispatchNewCalendarInfo(payload)}.
dispatchNewCalenderInfo should also be imported by the component:
import { dispatchNewCalendarInfo } from './redux/path/to/post/actions.js'; and connected to it: export default connect(()=>({}), { dispatchNewCalendarInfo })(Component);. Note, you need to also import connect from 'react-redux' for this.
And, of course, dispatchNewCalendarInfo should be present in the actions.js path, and accepted by the store reducer. This dispatch should alter information that the calendar is connected to, which will force it to update and re-paint.
If you're not using Redux there's another path you can take. Instead of having the function that takes input be in NewShift, have new shift receive the function as a prop from the parent.
So in your NewShift component you would have something like onClick={this.props.submitCalanderInfo()}
The submitCalanderInfo function would be part of the parent component. You would probably want this new info to be saved into the state of the parent component, and then then use that state to update the props on the calendar or Index component. So Index might look something like this:
<Index shiftData={this.state.shiftData} />

What are typical use cases for React lifecycle methods like componentWillReceiveProps

componentWillReceiveProps and other lifecycle methods seems like deceptive temptation to bring unnecessary complexity and noise to the code in the hands of inexperienced React coder. Why do they exist? What are their most typical use cases? In the moment of uncertainty, how would I know if the answer lies in the lifecycle methods?
I have been using react for couple of months now, and most of my work is creating a large application from scratch. So the same questions have presented themselves in the start.
The following information is based on learning while development and going through multiple docs out there to get it right.
As asked in the question here are couple of uses cases for the lifecycle methods in react
componentWillMount()
This is called once on the server side, if server side rendering is present, and once the client side.
I personally have used it just to do api calls which do not have direct effect on the components, for example getting oAuth tokens
componentDidMount()
This function is mostly used for calling API's (here is why to call it in componentDidMount and not in componentWillMount)
Components state initialisations which are based on the props passed by parents.
componentWillReceiveProps(nextProps,nextState)
This function is called every time props are received except the first render
Most common use I have encountered is to update the state of my current component which i can not do it in componentWillUpdate.
shouldComponentUpdate(nextProps, nextState)
This method is invoked before the render happens when new props or states are received. Here we can return false if the re-render is not required.
I see this as a performance optimisation tool. In case of frequent re-rendering of parent component this method should be used to avoid unnecessary update to current component
componentWillUpdate(nextProps,nextState)
this function is called every time a component is updated, it is not called when component mounts
Carry out any data processing here. For example, when a api fetch returns data, modelling the raw data into props to be passed to children
this.setState() is not allowed in this function , it is to be done in componentWillReceiveProps or componentDidUpdate
componentDidUpdate(prevProps,prevState)
Invoked right after the changes are pushed to the DOM
I have used it whenever the required data is not at the first render (waiting for api call to come through) and DOM requires to be changed based on the data received
Example, based on the age received show the user if he is eligible for application for an event
componentWillUnmount()
As the official docs mentions, any event listeners or timers used in the component to be cleaned here
In the moment of uncertainty, how would I know if the answer lies in
the lifecycle methods?
What analogy i suggest
Change is triggered in the component itself
Example, Enable editing of fields on click of an edit button
A function in the same component changes the state no involvement of lifecycle functions
Change is triggered outside of the component
Example, api call finished , need to display the received data
Lifecycle methods for the win.
Here are some more scenarios -
Does the change in state/props requires the DOM to be modified?
Example, if the current email is already present , give the input class an error class.
componentDidUpdate
Does the change in state/props requires to data to be updated?
Example, parent container which formats data received after api call and passes the formatted data to children.
componentWillUpdate
Props being passed to a child are changed , child needs to update
Example,
shouldComponentUpdate
Adding an event listener
Example, add a listener to monitor the DOM, based on window size.
componentDidMount
'componentWillMount' , to destroy the listner
Call api
'componentDidMount'
Sources -
Docs - https://facebook.github.io/react/docs/component-specs.html
this scotch.io article which cleared the lifecycle concepts
Event Listener - https://facebook.github.io/react/tips/dom-event-listeners.html
Some typical use cases for the most commonly used lifecycle methods:
componentWillMount: Invoked before initial rendering. Useful for making AJAX calls. For instance, if you need to grab the user information to populate the view, this is a good place to do it. If you do have an AJAX call, it would be good to render an indeterminate loading bar until the AJAX call finishes. I've also used componentWillMount to call setInterval and to disable Chrome's drag and drop functionality before the page renders.
componentDidMount: Invoked immediately after the component renders. Useful if you need to have access to a DOM element. For instance I've used it to disable copy and pasting into a password input field. Great for debugging if you need want to know the state of the component.
componentWillReceiveProps: Invoked when component receives new props. Useful for setting the state with the new props without re-rendering.
componentWillReceiveProps is part of Update lifce cycle methods and is called before rendering begins. The most obvious example is when new props are passed to a Component. For example, we have a Form Component and a Person Component. The Form Component has a single that allows the user to change the name by typing into the input. The input is bound to the onChange event and sets the state on the Form. The state value is then passed to the Person component as a prop.
import React from 'react';
import Person from './Person';
export default class Form extends React.Component {
constructor(props) {
super(props);
this.state = { name: '' } ;
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ name: event.currentTarget.value });
}
render() {
return (
<div>
<input type="text" onChange={ this.handleChange } />
<Person name={ this.state.name } />
</div>
);
}
}
Any time the user types into the this begins an Update for the Person component. The first method called on the Component is componentWillReceiveProps(nextProps) passing in the new prop value. This allows us to compare the incoming props against our current props and make logical decisions based on the value. We can get our current props by calling this.props and the new value is the nextProps argument passed to the method.

How do I do a simple onClick to change a child component's classname with React Redux?

I have React Redux working to change my child component's classname, but I do it via
//Subscribe with our function that sets our state
this.props.store.subscribe( this.onSelectChange );
(where the onSelectChange is a function in my component that changes a property on its state.
According to the redux docs, I should instead be using "a view binding library" like ReactRedux's connect method. But every tutorial is incredibly complex. They're hard to understand and appear to be about 5 times more code than what I need to use right now. Using Redux directly, I have about 6 lines of total code.
How can i simply use the "proper" way to make my child component change its classname?
If really all you need is to update a classname on click, React is perfectly capable of doing this without involving the Redux store.
The whole idea with React is that each component has some state object, and a render function to turn the state into markup. If you want to change your view, you should change the state and let React call render again. Take the following example which toggles the classname of a button (not tested):
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
highlighted: false
}
this.buttonClicked = this.buttonClicked.bind(this);
}
buttonClicked() {
var highlighted = !this.state.highlighted
this.setState({
highlighted: highlighted
})
}
render(){
var classname = this.state.highlighted ? "highlighted-btn" : "normal-btn"
return (
<button onClick={this.buttonClicked} className={classname} />
)
}
}
We trigger render by calling setState, in which we use the state to determine the classname for the button.
solution 1
well, if you change className because you want different style.
I will suggest you can use setState in its childComponent instead.
here is for your reference
solution 2
on the other hand, if you want to use Redux to achieve that.
you probably need to have a reducer first. let's say selectState
and then you need an action. here we name it changeSelectState
now, we can use connect from react-redux on the container component
and pass this method down to that presentational component. that's it.
So, the flow you can do is
add a reducer for storing data
add an action for changing the data
import that data and action via connect into container component
pass them down to presentational component
click and change the value via that action

Categories

Resources