using setState after function - javascript

i try it using setState after function in react, first run function , function finished after run setState({example:'example1'}) , how i can do it,
click button run loaded Variable with this.setState({loaded:false}), I will do the function setstate after the runtime this.setState({loaded:true}), how can it be done with a technique, i will use other code
container = () => { return (Balabla)} // is finish after 2.select
this.setState({loaded:true})
export default class search extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded:true
}
}
render(){
return(
<Loader loaded={this.state.loaded}/>
{this.container()}
)}
}

Probably you're asking for this, If I'm not wrong. You need an event-handler (onClick here) to call your respective function which changes the state. And also if your function is a paramless function, you shouldn't use the () in react while calling it.
container = () => { this.setState({loaded:true})}
render(){
return(
<Loader loaded={this.state.loaded} onClick={this.container}/>
)}

Related

How can I trigger a method in a subcomponent when parent changes props?

I have a React web application that has three components, a parent and two child subcomponents. I've left out the JavaScript related to <HeaderComponent /> because it isn't relevant to this question.
class App extends Component {
token = null;
constructor(props) {
super(props);
this.state = {
AllInvoices: [],
CurrentInvoice: null
};
this.setCurrentInvoice = this.setCurrentInvoice.bind(this);
}
setCurrentInvoice = (sharedValue) => {
this.setState({
CurrentInvoice: sharedValue
});
}
componentDidMount()
{
fetch("http://api.app.local/api/getALLinvoices", {
"method": "GET"
})
.then(resp => {
this.setState({
AllInvoices: resp.Result
CurrentInvoice: resp.Result[0]
});
});
}
componentDidUpdate()
{
// this DOES trigger
console.log("App componentDidUpdate triggered");
}
render() {
return (
<>
<HeaderComponent AllInvoices={this.state.AllInvoices} setCurrentInvoice={this.setCurrentInvoice} />
<MainFormComponent CurrentInvoice={this.state.CurrentInvoice} />
</>
)
}
}
class MainFormComponent extends Component {
token = null;
constructor(props) {
super(props);
this.state = {
Field1Value: "",
Field2Value: "",
Field3Value: "",
// ...
Field12Value: ""
};
}
componentDidUpdate()
{
//> For some reason this does NOT trigger when CurrentInvoice is updated
console.log("MainFormComponent componentDidUpdate triggered");
}
getInvoiceDetailsAndUpdateForm = () =>
{
fetch("http://api.app.local/api/getinvoicedetails", {
"method": "POST",
"body": {
"invoice_id": this.props.CurrentInvoice.Id
}
})
.then(resp => {
/*
* Run various business logic and update 12+ form fields with AJAX response
*
*/
});
}
render() {
return (
<>
<TextField Value={this.state.Field1Value} />
<TextField Value={this.state.Field2Value} />
<TextField Value={this.state.Field2Value} />
{ /* ... */ }
<TextField Value={this.state.Field12Value} />
</>
)
}
}
class HeaderComponent extends Component {
token = null;
constructor(props) {
super(props);
this.state = {
MiscVariable: ""
};
}
setUpdateCurrentInvoice = (row) =>
{
this.props.setCurrentInvoice(row);
}
render() {
return (
<>
{this.props.AllInvoices.map((row, i) => (
<Button onClick={() => { this.setUpdateCurrentInvoice(row); }} />
))}
</>
)
}
}
Within the App component an AJAX call returns all invoices, and sets an initial value for this.state.CurrentInvoice. Afterwards, buttons in <HeaderComponent /> or <MainFormComponent /> can change CurrentInvoice.
When CurrentInvoice within App is changed, I want to trigger getInvoiceDetailsAndUpdateForm within the <MainFormComponent /> so that I can perform another AJAX call and run other business logic within that component.
What I'm finding is that within <MainFormComponent /> I can't seem to be able to "subscribe" to props.CurrentInvoice value changes. Within the render() method in that Component I see the change. But, that hasn't helped me because I want to trigger getInvoiceDetailsAndUpdateForm.
Does anyone have any ideas on how I can achieve the outcome I want?
Update:
The original code I published did not contain code related to the HeaderComponent. I've now included that to help draw the whole picture.
Basically what's happening is that the user clicks on a button in HeaderComponent which then calls setCurrentInvoice. When this happens componentDidUpdate is triggered, but only in the parent component. I am trying to figure out why componentDidUpdate within MainFormComponent is NOT also firing.
What you are looking for is componentDidUpdate. You can compare prevProps and currentProps and perform necessary actions
you would want to implement this lifecycle method in your MainFormComponent
Also, here's this example which is emulating the behavior you are having.
if you see App is the component storing the state and the handler,
and ChildComponent has the componentDidUpdate in it
now when you click either in App or AnotherChildComponent
it fires the state update, since ChildComponent has ComponentDidUpdate and it is receiving the counter prop you can clearly see it printing the previous and current values.
One thing to note - componentDidUpdate does not get immediately fired but when the state/prop changes so you may not see it fired on the first render but as soon as your api returns something and updates the state you will see it's getting fired for the 1st time in your MainForm component
Also, if you can post some proof of it not firing like screenshot of console.log would be helpful.
I don't see a point of componentDidUpdate not firing.

Calling function in react native outside component

My requirement
I am calling my function placed outside of the component and view in react native, but it throws errors saying the _this.myfunction is undefined. Its clearly not getting the reference for the function. Is it possible to achieve such feature in react native.
class App extends React.Component {
constructor(props) {
super(props);
}
render () {
return (
<View style={styles.container}>
<Button onPress={() => this.Myfunction()} style={styles.Button} title="Button"/>
</View>
);
}
}
Myfunction () {
alert('clicked');
}
Since you've defined the function outside of the class, you don't need to refer it by this. You can simply write onPress={() => Myfunction()} or onPress={Myfunction}
Also your function's syntax is wrong, add the function keyword before it
function Myfunction () {
alert('clicked');
}

using a simple component (dumb) to create a list of buttons and use parent method

I'm trying to create a simple dashboard. I'm just exploring some new ideas I have in react and it's been so long I'm running into a strange problem I can't seem to understand.
I have a very simple class:
export default class Dashboard extends React.Component {
constructor(){
super();
}
HandleClick = (e) => {
if (e.name === "createEvent") {
console.log('event clicked');
}
console.log(e.name);
}
render() {
return(
<div className="row">
<ButtonList onClick={this.HandleClick}/>
</div>
)
}
}
and then I have a simple function outside of the class that creates a button list:
function ButtonList(props) {
return (
<button name="createEvent" onClick={props.HandleClick}>Create Event</button>
)
}
the idea behind this was instead of having so much stuff inside one superclass I wanted to separate simple functionality, like a button or command list if you will, that opon clicking would eventually change the state of the navbar.
I'm not sure how I would return that values of the button, or aside from that pass a parameter into the button from a child prop.
For example instead of doing HandleClick = (e) => and actually look for a parameter, how would I pass that in the child function where it gets used (if there were many more buttons)?
This is what you should be doing instead:
On your parent component, you can use arrow functions to pass the parameters within handleClick. This will allow you to listen to the events on your child ButtonList component with the parameters passed onto the method.
In addition, if you want to access to name attribute of your button, you should be calling event.target.name, as name is part of the target property of the Event interface.
export default class Dashboard extends React.Component {
constructor(){
super();
}
handleClick = (e) => {
if (e.target.name === "createEvent") {
console.log('event clicked');
}
console.log(e.target.name);
}
render() {
return(
<div className="row">
<ButtonList onClick={(e) => this.handleClick(e)} />
</div>
)
}
}
And on your ButtonList functional component, you should pass the onClick event to the onClick props which was defined as part of the ButtonList component.
function ButtonList(props) {
const onClick = (e) => {
props.onClick(e);
};
return (
<button name="createEvent" onClick={(e) => onClick(e)}>Create Event</button>
)
}
I have created a demo over here.

Manipulating DOM in componentDidMount() without setTimeout

I want to manipulate the DOM in ReactJS in the componentDidMount() method. My problem is that at this time the DOM isn't fully rendered somehow and I need a setTimeout function, which I would rather omit.
When I console.log the scrollHeight of the rendered element in componentDidMount() it gives me a different number as when I wait for let's say 100 milliseconds.
What I want to achieve is to scroll down to the end of an element which is described here How to scroll to bottom in react?
The component is a modal-window which renders {this.props.children} of another component. The modal-window is rendered into the DOM with visibility: hidden and opacity: 0 and it has the height of the window, when it first appears on the page. By clicking on a button it shows up and still has the height of the window until I wait some milliseconds.
I guess, I do something wrong here when setTimeout is needed, but I didn't found out what.
I also tried to change the DOM in the componentDidUpdate() method with the same results.
I wrote this code in the modal-window component:
componentDidMount() {
console.log(document.querySelector('.myModal').scrollHeight);
setTimeout(function() {
console.log(document.querySelector('.myModal').scrollHeight);
}, 100);
}
First console.log gives me for example 497 and the second one something like 952.
Update
I have a modal-window component which renders a child like this for example for my inbox-thread:
<Modal>
<InboxThread />
</Modal>
The problem was, that I needed to wait until the modal-window component rendered its children like this in the Modal.js:
render() {
return (
<React.Fragment>
{this.props.children}
</React.Fragment>
);
}
So my solution in the end was to hand over a method in the props from the parent component where I call the modal to check if componentDidUpdate() in Modal.js.
My code looks now like this in the parent component:
...
export default class InboxThreadList extends React.Component {
constructor(props) {
super(props);
this.scrollToModalBottom = this.scrollToModalBottom.bind(this);
}
render() {
return (
<React.Fragment>
...
<Modal onRender={this.scrollToModalBottom}>
<InboxThread/>
</Modal>
</React.Fragment>
)
}
scrollToModalBottom() {
const myModalObject = document.querySelector('.myModal');
myModalObject.scrollTop = myModalObject.scrollHeight;
}
}
And in the Modal.js:
...
export default class Modal extends React.Component {
...
componentDidUpdate() {
if ('onRender' in this.props) {
this.props.onRender();
}
}
render() {
return (
<div className={'myModal'}>
{this.props.children}
</div>
);
}
I know! I still should work with refs instead of document.querySelector and I will do as described here React - Passing ref from dumb component(child) to smart component(parent).
If you use a ref - as long as the element is always rendered in render() - it is guaranteed to resolve before componentDidMount runs:
componentDidMount() {
// can use any refs here
}
componentDidUpdate() {
// can use any refs here
}
render() {
// as long as those refs were rendered!
return <div ref={/* ... */} />;
}
componentDidMount called BEFORE ref callback
So in your case, you might code it a bit like this:
componentDidMount() {
console.log(this.mymodal.scrollHeight)
}
render() {
return <div className="mymodal" ref={ref => this.mymodal = ref} />
}

React Native Touchable Opacity functions

I have two functions in my React Native app, and I need my TouchableOpacity to call both when pressed. To do so I tried to simply use an arrow function in the onPress method with both functions inside, but this doesn't work. I assume it's something to do with scope, but I'm not sure. Both functions work correctly when simply passed into the onPress method alone. Here's the code (I've trimmed it a lot for readability) Please help.
export class CreateItem extends React.Component {
constructor(props){
super(props);
}
sendData = () => {
itemData = this.state.item;
this.props.action(itemData); //the action function alters the parent state (this function works fine every other time)
}
render(){
return(
<TouchableOpacity
onPress={() => {
this.sendData;
this.props.hide; //This function is passed from the parent and works fine in other scenarios
}}
>
<Text>Add Item</Text>
</TouchableOpacity>
)
}
you missed the parentheses of functions
export class CreateItem extends React.Component {
constructor(props){
super(props);
}
sendData = () => {
itemData = this.state.item;
this.props.action(itemData); //the action function alters the parent state (this function works fine every other time)
}
render(){
return(
<TouchableOpacity
onPress={() => {
this.sendData();
this.props.hide(); //This function is passed from the parent and works fine in other scenarios
}}
>
<Text>Add Item</Text>
</TouchableOpacity>
)
}

Categories

Resources