I'm new to react.
I have a function, that need to refresh the state according with API request result on my component.
How can i access that value?
Code (Example):
LoginComponent.js
class Login extends React.Component {
constructor(props){
super(props)
this.state = {
username : '',
password : ''
}
}
submit = (e) => {
/* console.logging "Some response"*/
console.log(this.props.doLogin(this.state))
}
render(){
return (
<form onSubmit={this.submit}>/* some login element */</form>
)
}
}
export default connect(null, {LoginAction})(Login);
LoginAction.js
export function doLogin(state){
return dispatch => {
return axios.post('login', state).then(res =>{
return "Some response";
})
}
}
you can do like this
for example create axios.js
import axios from 'axios';
var instance = axios.create({
baseURL: 'https://www.',
timeout: 1000,
headers: {'Authorization': 'Bearer xxx'}
});
export default instance;
then in your another screen
import React from 'react';
import API from '../axios';
export default class Profile extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
feedback: "",
id: "",
errors: {},
};
}
postComment = () => {
API.post(`/new-comment`, {
id: this.state.id,
feedback: this.state.feedback,
})
.then(res => res.data)
.then((response)=> {
this.setState({
feedback: '',
error: response.error || null,
})
}).catch(error => {console.log(error), this.setState({ error});});
}
Related
Iam trying to print back the value fetched from API. The data is coming but not able to set the state
Tried everything
React.js
import React, { Component } from 'react'
import axios from 'axios'
class Admin extends Component {
constructor(props) {
super(props)
this.state = {
users: []
}
}
componentDidMount(){
axios.get('/api/adminUsers')
.then(response =>{
this.setState({users: response.data})
console.log(response.data)
console.log(this.setState({users: response.data}))
})
.catch(error=>{
this.setState({ errorMsg: "Something is wrong here"})
console.log(error)
})
}
render() {
const{users} = this.state
<div>
{
users.length ?
users.map(user => <div key=
{user.id}>{user.name}</div>)
: null
}
</div>
)
}
}
export default Admin
The response.data showing in console is:
{[
created_at: "2019-08-31 14:06:29"
email: "amit.khare588#gmail.com5"
email_verified_at: null
id: 2
name: "Amit Khare"
role: "Doctor"
updated_at: "2019-08-31 14:06:29"
]}
I just want to print the data back
The code seems fine below is a fully working example:
import React from "react";
import ReactDOM from "react-dom";
class Admin extends React.Component {
constructor(props) {
super(props)
this.state = {
users: [],
errorMsg: ''
}
}
componentDidMount() {
axios.get('/api/adminUsers')
.then(response => {
this.setState({users: response.data.users})
console.log(response.data)
})
.catch(error => {
this.setState({errorMsg: "Something is wrong here"})
console.log(error)
})
}
render() {
const {users, errorMsg} = this.state;
return <div>
{users.length ? users.map(user => <div key={user.id}>{user.name}</div>) : null}
{errorMsg ? <div>{errorMsg}</div> : null}
</div>
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Admin/>, rootElement);
Checkout the codesandbox: https://codesandbox.io/s/nice-fermi-ku1jr
I am trying to use React's context api to manage a global state. When I try to invoke contextual methods or access contextual proprties, I get errors saying "this.context.setUser function does not exist" or "undefined".
I have however been able to hard code values into the state of the context and retreive the hardcoded value.
Feed Context
import React, { Component } from 'react'
const FeedContext = React.createContext({
Feed: [],
user: '',
error: null,
setError: () => {},
clearError: () => {},
setFeed: () => {},
setUser: () => {}
})
export default FeedContext
export class FeedProvider extends Component {
state = {
feed: [],
error: null,
user: ''
};
setUser = user => {
this.setState({ user })
}
setFeed = Feed => {
this.setState({ Feed })
}
setError = error => {
console.error()
this.setState({ error })
}
clearError = () => {
console.log('context is accessed')
this.setState({ error: null })
}
render() {
const value = {
feed: this.state.feed,
error: this.state.error,
setError: this.setError,
clearError: this.clearError,
setFeed: this.setFeed,
setUser: this.setUser
}
return (
<FeedContext.Provider value={value}>
{this.props.children}
</FeedContext.Provider>
)
}
}
AccountPanel.js
import React from 'react';
import FeedContext from "../../contexts/FeedContext";
// functional component
class AccountPanel extends React.Component {
static contextType = FeedContext
renderUserInfo(){
const { user = [] } = this.context;
//this returns "undefined"
console.log(user.user)
//this returns "user.setUser() is not a function"
user.setUser('newUser')
//this returns ' '
this.context.setUser('y')
console.log(user)
}
render(){
return (
<section>
{ this.renderUserInfo() }
AccountPanel
</section>
)
}
}
export default AccountPanel;
I would like to be able to update the contextual state/user via this.context.setUser('newUser), then consume that value in my navbar component
File App.js
import React, { Component } from 'react';
import AccountPanel from "./components/AccountPanel";
import { FeedProvider } from './components/FeedContext';
class App extends Component {
render() {
return (
<div className="App">
<FeedProvider>
<AccountPanel />
</FeedProvider>
</div>
);
}
}
export default App;
File : FeedContext.js
import React, { Component } from 'react'
const FeedContext = React.createContext({
Feed: [],
user: '',
error: null,
setError: () => {},
clearError: () => {},
setFeed: () => {},
setUser: () => {}
})
export default FeedContext
export class FeedProvider extends Component {
constructor(props){
super(props);
this.state = {
feed: [],
error: null,
user: "11"
};
}
setUser = user => {
console.log(`setting usr fns called for username: ${user}`);
this.setState({ user });
}
setFeed = Feed => {
this.setState({ Feed })
}
setError = error => {
console.error()
this.setState({ error })
}
clearError = () => {
console.log('context is accessed')
this.setState({ error: null })
}
componentDidMount(){
console.log('FeedProvider:componentDidMount');
}
render() {
let value1 = {
Feed:this.state.feed,
user:this.state.user,
error:this.state.error,
setError:this.setError,
clearError:this.clearError,
setFeed:this.setFeed,
setUser:this.setUser
}
return (
<FeedContext.Provider value={value1}>
{this.props.children}
</FeedContext.Provider>
)
}
}
File : AccountPanel.js
import React from 'react';
import FeedContext from "./FeedContext";
// functional component
class AccountPanel extends React.Component {
static contextType = FeedContext
// return BlogPost component html/(JSX)
componentDidMount(){
console.log('AccountPanel:componentDidMount');
console.log(this.context);
const value = this.context;
//this returns "undefined"
console.log(value.user)
//this returns "user.setUser() is not a function"
console.log(value.setUser);
value.setUser('newUser');
}
render(){
const value = this.context;
console.log(`Value of new User is : ${value.user}`);
return (
<section>
AccountPanel
</section>
)
}
}
export default AccountPanel;
Hope This helps :)
Aim :
I want to put firstName and lastName on my Navbar. So, I'm using axios request by id with userId
EDIT: Thanks to #Isaac, I have no more infinite loop when I'm using componentWillUpdate() now.
Problem : Data doesn't change (firstName and lastName) when I'm logout and login with another account
No problems from servers.
here a picture :
Description : I've login as a & g (firstName and lastName), then I've logout and login as j & j.
navbar.js:
import React, { Component } from 'react';
import { fade } from '#material-ui/core/styles/colorManipulator';
import { withStyles } from '#material-ui/core/styles';
import { connect } from 'react-redux';
import AuthA from '../store/actions/AuthA';
import { withRouter } from 'react-router-dom';
import '../Navbar.css';
import NavbarV from './NavbarV';
import PropTypes from 'prop-types';
import axios from 'axios';
class NavbarC extends Component {
constructor(props){
super(props);
this.state = {
client:[]
}
}
componentWillMount(){
this.getUser();
}
getUser(){
axios.get (`http://localhost:3002/api/clients/${localStorage.getItem("userId")}?access_token=${localStorage.getItem("token")}`)
.then(res => {
this.setState({client: res.data}, () => {
console.log(this.state)
})
})
}
shouldComponentUpdate(nextState){
return (this.state.client.firstName !== nextState.firstName ||
this.state.client.lastName !== nextState.lastName);
}
componentWillUpdate(){
this.getUser();
console.log(this.state)
}
logout = () => {
this.props.authfn.logout();
};
render() {
return(
<NavbarV logout = {this.logout}
firstName={this.state.client.firstName}
lastName={this.state.client.lastName}
userId={this.props.userId}
auth = {this.props.auth}
classes={this.props.classes}/>
)
}
}
NavbarC.propTypes = {
auth: PropTypes.bool.isRequired,
firstName: PropTypes.string.isRequired,
lastName: PropTypes.string.isRequired
};
const mapStateToProps = (state) => {
return {
auth: state.AuthR.auth,
firstName: state.AuthR.firstName,
lastName: state.AuthR.lastName,
userId: state.AuthR.userId
};
};
const mapDispatchToProps = dispatch => {
return {
authfn: AuthA(dispatch)
}
};
export default connect(mapStateToProps, mapDispatchToProps) (withStyles(styles)(withRouter(NavbarC)));
If someone have a solution or any questions, I'm here :)
thank you all in advance
First of all, you should avoid componentWillUpdate lifecycle as it's been deprecated.
And for your case, this.getUser(); will be triggered to pull data which then trigger this.setState({client: res.data}). When the app executing this.setState(), your component will be re-render so there's no need to have any other componentLifeCycle.
class NavbarC extends Component {
state = { client:[], userID: null, token: null };
componentDidMount(){
this.setState({
userID: localStorage.getItem("userId"),
token: localStorage.getItem("token")
}, () => {
this.getUser();
})
}
getUser(){
axios.get (`http://localhost:3002/api/clients/${this.state.userID}?access_token=${this.state.token}`)
.then(res => {
this.setState({ client: res.data }, () => {
console.log(this.state)
})
})
}
componentDidUpdate(prevProps, prevState){
if(prevState.userID !== this.state.userID) {
this.getUser();
}
}
logout = () => this.props.authfn.logout();
render() {
return(
<NavbarV
logout = {this.logout}
firstName={this.state.client.firstName}
lastName={this.state.client.lastName}
userId={this.props.userId}
auth = {this.props.auth}
classes={this.props.classes} />
)}
}
I solve it !
This is a solution :
componentDidMount(){
this.setState({
userId: localStorage.getItem("userId"),
token: localStorage.getItem("token")
}, () => {
this.getUser();
})
}
getUser = () => {
axios.get (`http://localhost:3002/api/clients/${this.state.userId}?access_token=${this.state.token}`)
.then(res => {
this.setState({ client: res.data, userId: localStorage.getItem("userId") }, () => {
console.log(this.state)
})
})
}
componentDidUpdate(prevProps, prevState){
if(prevState.userId !== this.props.userId) {
this.setState({ userId: this.props.userId }, () => {
this.getUser();
})
}
}
Hello I have problem to set state variable in url parameter. I have tried few example I found in internet, but no one works for me.
I tried this:
constructor(props) {
super(props);
this.state = {
channelId: []
};
}
componentDidMount() {
this.setState({ channelId: '1ae2275e-2ca2-42cb-be13-e97b59fbae13' });
}
componentWillMount() {
fetch(
`http://localhost:8080/api/channel/${this.state.channelId}`)
.then...
And this:
constructor(props) {
super(props);
this.state = {
channelId: []
};
componentDidMount() {
this.setState({ channelId: '1ae2275e-2ca2-42cb-be13-e97b59fbae13' });
}
componentWillMount() {
fetch(
`http://localhost:8080/api/channel/'+this.state.channelId)
.then...
None of them are setting value in url. Maybe someone could tell me what I am doing wrong?
componentWillMount called before componentDidMount
-> so in componentWillMount, this.state.channelId = []
I think, you should set state of channelId in ComponentWillMount and call api in componentDidMount
constructor(props) {
super(props);
this.state = {
channelId: ''
};
componentWillMount() {
this.setState({ channelId: '1ae2275e-2ca2-42cb-be13-e97b59fbae13' });
}
componentDidMount() {
fetch(
`http://localhost:8080/api/channel/'+this.state.channelId)
.then...
And with react 16, react doesn't recommend using componentWillMount in new code (Details: https://reactjs.org/docs/react-component.html#unsafe_componentwillmount)
So the first thing is to set channelId to a string and not an array.
constructor(props) {
super(props);
this.state = {
channelId: ''
}
Let me ask why you want to use componentWillMount... From my experience, it sometimes adds a lifecycle that is not necessarily useful.
Have you tried
constructor(props) {
super(props);
this.state = {
channelId: ''
};
componentDidMount() {
this.getChannelId()
}
getChannelId() {
this.setState({
channelId: '1ae2275e-2ca2-42cb-be13-e97b59fbae13'
});
return fetch( `http://localhost:8080/api/channel/${this.state.channelId}`)
.then(res => {
// your code
})
}
?
I used a "similar" approach for an app of mine:
import React, { Component } from 'react';
import { connect} from 'react-redux';
import { API_BASE_URL } from '../config';
import { Weekday, Weekendday } from './Day';
import './Availability.css';
const currentUserId = localStorage.getItem("id");
export class Availability extends Component {
constructor(props) {
super(props);
this.state = {
availability: {},
loading: false,
error: null
};
}
componentDidMount() {
this.loadAvailability()
}
loadAvailability() {
this.setState({
loading: true
});
return fetch(`${API_BASE_URL}/employee/${currentUserId}/availability`)
.then(res => {
if (!res.ok) {
return Promise.reject(res.statusText);
}
return res.json();
})
.then(availability => {
console.log(availability)
this.setState({
availability,
loading: false
})
})
.catch(err => {
this.setState({
error: 'Could not load availability list',
load: false
})
console.log(this.state.error, err)
})
}
...
Also do you mind sharing the rest of your code for that component so we can see when you need another change of state?
Thanks!
I am trying to fetch the message outputted by the following endpoint:
http://helloworld-env-2.5fwknpgms8.us-east-2.elasticbeanstalk.com/
I just ran a create-react-app to create my application and changed the code in the App.js file
New Code:
import React, { Component } from 'react';
import './App.css';
class App extends React.Component {
constructor(props){
super(props);
this.state = {
error: null,
isLoaded: false,
items: ""
};
}
componentDidMount(){
console.log("mounting component");
fetch("http://helloworld-env-2.5fwknpgms8.us-east-2.elasticbeanstalk.com/")
.then((result) => {
this.setState({
isLoaded: true,
items: result
});
});
}
render() {
console.log("rendering");
const isLoaded = this.state.isLoaded;
if(isLoaded){
return (<div> {this.state.items} </div>);
}
else{
return (
<div>loading</div>
);
}
}
}
export default App;
I keep getting the loading message.
You need to parse the response from fetch:
componentDidMount(){
fetch("http://helloworld-env-2.5fwknpgms8.us-east-2.elasticbeanstalk.com/")
.then((result) => result.json()) // here
.then((result) => {
const { a } = result; // access 'a' key from response
this.setState({
isLoaded: true,
items: a
});
});
}
Here are the docs.