React axios request in ComponentDidMount not passing data as props to component - javascript

Hi guys I can't see my Error here hope someone can hlep...
This is my fetch Data class:
export default class Auftrag extends Component {
state = {
auftraege: "Test",
};
getAuftraege = () => {
axios.get("Auftraege/auftraege").then(e => {
this.setState({
auftraege: e.data,
});
console.log(e.data);
});
};
componentDidMount() {
this.getAuftraege();
}
render() {
return (
<>
<AuftragDisplay test={this.state.auftraege} ></AuftragDisplay>
</>
);
}
}
And this is my constructor in my Display class:
constructor(props) {
super(props);
console.log(props);
}
The axios Request is getting fired and I get the right data in my console. But It is not getting passed to my Component.
Hope someone knows whats wrong and can help me
SOLVED:
Thx to san I tried it and could solve the problem. I got the data passed but console.log() was called before the update so I got the old data. THX again

Your code looks fine. you can see below same code with different api as an example
class Auftrag extends Component {
state = {
auftraege: "Test",
};
getAuftraege = () => {
axios
.get("https://jsonplaceholder.typicode.com/posts/1")
.then(e => this.setState({auftraege: e.data}))
};
componentDidMount() {
this.getAuftraege();
}
render() {
return (
<>
<AuftragDisplay test={this.state.auftraege} ></AuftragDisplay>
</>
);
}
}
const AuftragDisplay = ({test}) =><h2>Hi--->{test.title}</h2>

Just put the state inside constructor of Auftrag class, I should work.

Related

React setState doesn't update the state

I am currently using react-modal in my project and i have problem opening and closing it probably from other component.
class MainComponent {
constructor() {
this.state = {reportOpen: false};
}
closeReport = (e) => {
this.setState({reportOpen: false}, () =>
console.log(this.state.reportOpen)); // This line print true !!!
}
render() {
return (
<Button onClick={(e) => this.setState({reportOpen: true})}/>
<ReportModal isOpen={this.state.reportOpen} onClose= .
{this.closeReport}/>
)
}
}
// Modal
class ReportModal {
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.isOpen !== prevState.isOpen) {
return ({isOpen: nextProps.isOpen});
}
else {
return null;
}
}
render() {
return <Modal isOpen={this.state.isOpen}
onRequestClose={this.props.onClose}
shouldCloseOnOverlayClick={true}
shouldCloseOnEsc={true}/>
}
}
Due to the mentioned problem, I couldn't close the modal once i opened it. Please help me to figure out the problem here. Thanks for any help.
Missing extends React.Component in class declaration.
Missing super(props); call in constructor.
Please debug at getDerivedStateFromProps for the new derived state.
Also why don't you just handle the same in ReportModal component, the callback seems overwork

set multiple states, and push to state of array in one onClick function

I'm running into a recurring issue in my code where I want to grab multiple pieces of data from a component to set as states, and push those into an array which is having its own state updated. The way I am doing it currently isn't working and I think it's because I do not understand the order of the way things happen in js and react.
Here's an example of something I'm doing that doesn't work: jsfiddle here or code below.
import React, {Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
categoryTitle: null,
categorySubtitle: null,
categoryArray: [],
}
}
pushToCategoryArray = () => {
this.state.categoryArray.push({
'categoryTitle': this.state.categoryTitle,
'categorySubtitle': this.state.categorySubtitle,
})
}
setCategoryStates = (categoryTitle, categorySubtitle) => {
this.setState({
categoryTitle: categoryTitle,
categorySubtitle: categorySubtitle,
})
this.pushToCategoryArray();
}
render() {
return (
<CategoryComponent
setCategoryStates={this.setCategoryStates}
categoryTitle={'Category Title Text'}
categorySubtitle={'Category Subtitle Text'}
/>
);
}
}
class CategoryComponent extends Component {
render() {
var categoryTitle = this.props.categoryTitle;
var categorySubtitle = this.props.categorySubtitle;
return (
<div onClick={() => (this.props.setCategoryStates(
categoryTitle,
categorySubtitle,
))}
>
<h1>{categoryTitle}</h1>
<h2>{categorySubtitle}</h2>
</div>
);
}
}
I can see in the console that I am grabbing the categoryTitle and categorySubtitle that I want, but they get pushed as null into this.state.categoryArray. Is this a scenario where I need to be using promises? Taking another approach?
This occurs because setState is asynchronous (https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly).
Here's the problem
//State has categoryTitle as null and categorySubtitle as null.
this.state = {
categoryTitle: null,
categorySubtitle: null,
categoryArray: [],
}
//This gets the correct values in the parameters
setCategoryStates = (categoryTitle, categorySubtitle) => {
//This is correct, you're setting state BUT this is not sync
this.setState({
categoryTitle: categoryTitle,
categorySubtitle: categorySubtitle,
})
this.pushToCategoryArray();
}
//This method is using the state, which as can be seen from the constructor is null and hence you're pushing null into your array.
pushToCategoryArray = () => {
this.state.categoryArray.push({
'categoryTitle': this.state.categoryTitle,
'categorySubtitle': this.state.categorySubtitle,
})
}
Solution to your problem: pass callback to setState
setCategoryStates = (categoryTitle, categorySubtitle) => {
//This is correct, you're setting state BUT this is not sync
this.setState({
categoryTitle: categoryTitle,
categorySubtitle: categorySubtitle,
}, () => {
/*
Add state to the array
This callback will be called once the async state update has succeeded
So accessing state in this variable will be correct.
*/
this.pushToCategoryArray()
})
}
and change
pushToCategoryArray = () => {
//You don't need state, you can simply make these regular JavaScript variables
this.categoryArray.push({
'categoryTitle': this.state.categoryTitle,
'categorySubtitle': this.state.categorySubtitle,
})
}
I think React doesn't re-render because of the pushToCategoryArray that directly change state. Need to assign new array in this.setState function.
// this.state.categoryArray.push({...})
const prevCategoryArray = this.state.categoryArray
this.setState({
categoryArray: [ newObject, ...prevCategoryArray],
)}

React: Calling setState within render method throws error

As the title suggests, only after the first message received in my chat-window - this initial message is retrieved from a GET request so it's not synchronous - I want to show/render a button. At the moment it throws an error saying I cant set the state within the render method.
I also tried the show logic in the button class as well as the 'parent' class which is my messagelist which I'm putting the button in its render method.
There is this.props.messages which is an array of the messages and so is 'messages'. this.props.messages[0].data.text is the first message, although it does console many times each messsage in the dev tools when i try console it, and of course it throws the setState error when i try to show the button.
I have a simple button class:
class Button extends Component {
render() {
return (
<div>
{<button>Return</button >}
</div>
)
}
}
export default Button;
and my messageList class, where I have the this.props.messages which is an array of the messages, this.props.messages[0] is the first message , and message..which console's every single message if i console.log it.
If i write either (if message.data.text OR this.props.messages[0] === 'my first string') { console.log ('..... '}then it always counts as true and consoles and the setstate goes into a loop.
import Message from './Messages'
import Button from './Button'
class MessageList extends Component {
constructor(props) {
super(props);
this.state = {
showing: false,
};
this.showButton = this.showButton.bind(this);
}
showButton() {
const { showing } = this.state;
this.setState({
// toggle value of `showing`
showing: !showing,
});
}
componentDidUpdate(prevProps, prevState) {
this.scrollList.scrollTop = this.scrollList.scrollHeight;
}
onlyInitialMessage(message) {
if (this.props.messages[0].data.text = `Hi I'm Joe your store assistant, I'm here to help. Here's what I can do: Answer questions on store policies, process a return or just general inquiries.`) {
this.showButton();
}
}
// way to render a function.
// {this.renderIcon()}
render() {
return (
<div className="sc-message-list" ref={el => this.scrollList = el}>
{this.props.messages.map((message, i) => {
{ this.onlyInitialMessage() }
return <Message message={message} key={i} />
})}
{this.state.showing && <Button />}
</div>)
}
}
I'm not sure If I have my logic in the wrong place here? I tried to move it around lots of times, I am new to React!
Firstly, The issue is that you are setting state in the render method indirectly by calling { this.onlyInitialMessage() } in render.
Secondly, your if condition is not comparing value but assinging value which will always return true
if (this.props.messages[0].data.text === `Hi I'm Joe your store assistant, I'm here to help. Here's what I can do: Answer questions on store policies, process a return or just general inquiries.`) {
To solve it, you must call onlyInitialMessage within componentDidMount
import Message from './Messages'
import Button from './Button'
class MessageList extends Component {
constructor(props) {
super(props);
this.state = {
showing: false,
};
this.showButton = this.showButton.bind(this);
}
componentDidMount() {
this.onlyInitialMessage();
}
showButton() {
const { showing } = this.state;
this.setState({
// toggle value of `showing`
showing: !showing,
});
}
componentDidUpdate(prevProps, prevState) {
this.scrollList.scrollTop = this.scrollList.scrollHeight;
}
onlyInitialMessage(message) {
if (this.props.messages[0].data.text == `Hi I'm Joe your store assistant, I'm here to help. Here's what I can do: Answer questions on store policies, process a return or just general inquiries.`) {
this.showButton();
}
}
// way to render a function.
// {this.renderIcon()}
render() {
return (
<div className="sc-message-list" ref={el => this.scrollList = el}>
{this.props.messages.map((message, i) => {
return <Message message={message} key={i} />
})}
{this.state.showing && <Button />}
</div>)
}
}

React "Cannot read property 'bind' of undefined"

I looked at many other answers but I couldn't figure it out. Here is my code:
// userInputActions.js
...
export function dummy() {
console.log('dummy function called');
}
...
// *userInputPage.js*
import * as userInputActions from '../actions/userInputActions';
class UserInput extends React.Component {
constructor(props) {
super(props);
this.state = {
};
// When un-commented it shows '*f dummy()*' is imported
// console.log('actions: ', userInputActions);
this.dummy = this.dummy.bind(this);
}
render () {
return (
<div className="container-fluid align-items-center">
<FieldLevelValidationForm onSubmit={this.dummy}/>
</div>
);
}
}
const mapStateToProps = (state) => ({
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators(
{
...userInputActions
}, dispatch
);
export default connect(mapStateToProps, mapDispatchToProps)(UserInput);
Note 'FieldLevelValidationForm' is a redux-form and onSubmit is one of the form function arguments.
I tried various things and the bind function does not work. Can someone please let me know where am I going wrong. I think it has something to do with the render() function and the lifetime of the component but I do not know enough yet.
Edit
Thank you - learned a lot from all answers. All of them work. I wish I could give more than one check-mark. However, I think the most appropriate use for my case is to call it as a prop and dispatch an action as so on.
The dummy function is passed as props, so you should access it with this.props.dummy in your render() instead.
There's also no need to bind it to this as it's not using the this instance.
The dummy function you are trying to bind is not in this class. So it would just be:
this.dummy = userInputActions.dummy.bind(this);
Function definition of dummy is missing.
constructor(props) {
super(props);
this.state = { };
this.dummy = this.dummy.bind(this);
}
dummy(e) {
// form submission action
userInputActions.dummy(); // maybe
}
render () {
return (
<div className="container-fluid align-items-center">
<FieldLevelValidationForm onSubmit={this.dummy}/>
</div>
);
}

pass function to child component using react reorder

I am stuck with passing function to child component of Reorder
Parent Component (some part of code)
import Reorder from 'react-reorder';
constructor() {
super();
this._bind(
'_changeStatusReorder'
);
this.state = {
status: true
};
}
_changeStatusReorder() { //my function
console.log('_changeStatusReorder');
this.setState({
status: false
});
}
return (
<div className={styles.main}>
<Reorder
...
...
sharedProps={{changeStatus: this._changeStatusReorder}} //pass function to props
/>
</div>
);
and the child component
_handleMouseDown() {
const {sharedProps: {changeStatus}} = this.props;
console.log(sharedProps); //try to see at console
setTimeout(() => {
},0);
}
I got "Uncaught ReferenceError: sharedProps is not defined" in the console, so
i don't know what i am wrong. i can't solve it.
Try to use sharedProps={this._changeStatusReorder}. And use in child component with this.props.sharedProps()

Categories

Resources