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!
Related
What I want to do
When a child component first rendering, I would like to use the value in props from a parent component
Problem
When a child component is first rendered, props is not set to state in the child component
I am a beginner to React. I am trying to use props in order to call API by axios in componentDidMount in a child component. I mean, what I am doing is calling API in a parent component and setting data from this API to a child component as props.
However, when I try to do that, props is not set to state in a child component.
For example, when I retrieve product which has some category, I type localhost:3000/api/parent/?category=1/. But, my console.log shows me localhost:3000/api/parent/?category=undefined because I guess props is not set when a child component first rendering.
Actually, I can see category object in state like below.
I guess props is completely set to state after the child component finish first rendering.
How could I set props which comes from API to state?
Although I tried many solutions I found on the stackoverflow, I got stuck at this problem so long time.
I would like you to tell me some solutions.
Thank you very much.
== == ==
My code is like this.
Parent Component
class Top extends Component {
constructor(props) {
super(props);
this.state = {
loginUser: '',
categories: [],
};
}
async componentDidMount() {
const localhostUrl = 'http://localhost:8000/api/';
const topCategoryList = ['Smartphone', 'Tablet', 'Laptop'];
let passCategoryToState=[]
axios
.get(localhostUrl + 'user/' + localStorage.getItem('uid'))
.then((res) => {
this.setState({ loginUser: res.data });
})
.catch((err) => console.log(err));
await Promise.all(
topCategoryList.map(async (category) => {
await axios.get(localhostUrl + 'category/?name=' + category).then((res) => {
passCategoryToState=[...passCategoryToState, res.data]
console.log(passCategoryToState);
});
})
);
this.setState({categories : passCategoryToState})
}
render() {
if (!this.props.isAuthenticated) {
return <p> Developing now </p>;
}
if (this.state.loginUser === '' ) {
return <CircularProgress />;
} else {
return (
<>
<Header loginUser={this.state.loginUser} />
<Give_Item_List
axiosUrl="http://localhost:8000/api/"
subtitle="Smartphone Items"
loginUser={this.state.loginUser}
category={this.state.categories[0]}
/>
</>
);
}
}
}
export default Top;
And, child component
class Give_Item_List extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
loginUser: this.props.loginUser,
category: this.props.category,
};
}
async componentDidMount() {
let pickedGiveItems;
await this.setState({ loading: true });
await axios
.get(this.props.axiosUrl + 'giveitem/?category=' + this.state.category.id)
.then((res) => {
pickedGiveItems = res.data;
console.log(pickedGiveItems);
})
.catch((err) => console.log('Not found related to Items'));
this.setState({ loading: false });
}
render() {
if (this.state.loading == true) {
return <CircularProgress />;
}
return <h1>Give_Item_List</h1>;
}
}
export default Give_Item_List;
==============
Edit:Change to componentDidUpdate
componentDidUpdate(prevProps) {
if(prevProps.category != this.props.category){
let pickedGiveItems;
this.setState({ loading: true });
axios
.get(this.props.axiosUrl + 'giveitem/?category=' + this.props.category.id)
.then((res) => {
pickedGiveItems = res.data;
console.log(pickedGiveItems);
})
.catch((err) => console.log('NotFount'));
this.setState({ loading: false });
}
}
It still doesn't work...
In the constructor, this.props is undefined, but you can access the props directly.
constructor(props) {
super(props);
this.state = {
loading: false,
loginUser: props.loginUser,
category: props.category,
};
}
However, I should note now that storing props in state is a common react anti-pattern, you should always consume prop values from this.props where you need them.
For example:
async componentDidMount() {
let pickedGiveItems;
await this.setState({ loading: true });
await axios
.get(this.props.axiosUrl + 'giveitem/?category=' + this.props.category.id)
.then((res) => {
pickedGiveItems = res.data;
console.log(pickedGiveItems);
})
.catch((err) => console.log('Not found related to Items'));
this.setState({ loading: false });
}
You also can't await a react state update since it isn't an async function nor does it return a Promise. Just provide an initial true loading state and toggle false when the fetch request resolves.
class Give_Item_List extends Component {
constructor(props) {
super(props);
this.state = {
loading: true
};
}
async componentDidMount() {
let pickedGiveItems;
await axios
.get(this.props.axiosUrl + 'giveitem/?category=' + this.props.category.id)
.then((res) => {
pickedGiveItems = res.data;
console.log(pickedGiveItems);
})
.catch((err) => console.log('Not found related to Items'));
this.setState({ loading: false });
}
render() {
if (this.state.loading) {
return <CircularProgress />;
}
return <h1>Give_Item_List</h1>;
}
}
I'm creating a block for Wordpress with Gutenberg Editor, which is working on React js.
So I'm calling Wordpress API by apiFetch(), which is same to fetch():
class PortfolioTagsEdit extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: false,
};
}
componentDidMount() {
const { attributes } = this.props;
const { switcher } = attributes;
this.setState({ isLoading: true });
apiFetch( { path: `/wp/v2/${switcher}?post` } )
.then(data => this.setState({ data, isLoading: false }));
}
...
}
For variable switcher I have controllers which are changing the value.
My problem is when I switch the value of switcher I should reload api call, but I don't know how)
Can you help me, please?
Using react hooks you can use useEffect for fetching API.
function PortfolioTagsEdit({ attributes }) {
// state
const [loading, setLoading] = useState(false);
const [data, setData] = useState([])
// here useEffect will run on component mount and every-time attributes.switcher changes
useEffect(() => {
setLoading(true)
apiFetch( { path: `/wp/v2/${switcher}?post` } )
.then(data => {
setLoading(false)
setData(data)
});
}, [attributes.switcher])
return (
....
)
}
The easiest way to do this would be to have the switcher variable in state. You can then implement the componentDidUpdate method to call your apiFetch:
class PortfolioTagsEdit extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: false,
switcher: this.props.attributes.switcher
};
}
componentDidMount() {
this.callAPI()
}
componentDidUpdate(prevProps, prevState) {
if (prevState.switcher !== this.state.switcher) this.callAPI();
}
callAPI() {
const { switcher } = this.state;
this.setState({ isLoading: true });
apiFetch( { path: `/wp/v2/${switcher}?post` } )
.then(data => this.setState({ data, isLoading: false }));
}
...
}
Check out the docs for componentDidUpdate - https://reactjs.org/docs/react-component.html#componentdidupdate
You could also take a look on how to do this using hooks, specifically useEffect -https://reactjs.org/docs/hooks-reference.html#useeffect
I want to pass my data array and favorites array which both I am setting in states. I want to pass my favorites array state in my data state. How can I achieve that?? My code looks like this
class Favorites extends Component {
constructor(props) {
super(props);
this.state = {
favorites: [],
data: [],
};
}
axios
.post(
'http://staging.islamicmedia.com.au/wp-json/islamic-media/v1/user/media/library',
data,
)
.then((res) => {
console.log(res.data);
this.setState({
data: res.data,
favorites: res.data.data.favorite.filter((val) => val != null),
});
});
};
You should do that axios call in the componentDidMount:
class Favorites extends Component {
constructor(props) {
super(props);
this.state = {
favorites: [],
data: [],
};
}
componentDidMount() {
axios
.post(
'http://staging.islamicmedia.com.au/wp-json/islamic-media/v1/user/media/library',
data,
)
.then((res) => {
const favs = res.data.data.favorite.filter((val) => val !== null);
this.setState({
data: res.data,
favorites: favs
});
});
};
}
I have a reactjs application.
In this I want to manage a list from parent component.
This application can add a object to list, delete it from list and show added objects in a table.
My problem is that I can add an object, but must refresh the whole page that it is shown in the list.
The two way binding not work and I don't know how to implement it.
I hope you can help me.
class Wrap extends React.Component{
constructor(){
super();
this.state = {
player: []
};
}
render(){
return(
<div id ="wrapperComponent">
<Table/>
<Create />
</div>
);
}
}
class Table extends React.Component {
constructor(props) {
super(props);
this.state = {
player: []
};
this.deletePlayer = this.deletePlayer.bind(this);
}
componentDidMount() {
axios.get('http://localhost:8081/player')
.then(res => {
this.setState({ player: res.data });
console.log(this.state.player);
});
}
deletePlayer(id) {
fetch(`http://localhost:8081/player/${id}`, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}).then(() => {
let updatedPlayers = [...this.state.player].filter(i => i.id !== id);
this.setState({player: updatedPlayers});
});
}
class Create extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
ownerid: ''
};
}
onChange = (e) => {
const state = this.state
state[e.target.name] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
e.preventDefault();
const { name, ownerid} = this.state;
axios.post('http://localhost:8081/player', { name, ownerid})
.then(() => this.setState(() => ({
})))
}
```
Add your .get call in a method in parent component and pass it as props. Use it to refresh your list.
class Wrap extends React.Component {
constructor() {
super();
this.state = {
players: []
};
}
getData = () => {
axios.get('http://localhost:8081/player')
.then(res => {
this.setState({ players: res.data });
});
}
removePlayerFromState = (id) => {
let updatedPlayers = [...this.state.players].filter(i => i.id !== id);
this.setState({players: updatedPlayers});
}
render() {
return (
<div id="wrapperComponent">
<Table getData={this.getData} players={this.state.players} removePlayerFromState={this.removePlayerFromState}/>
<Create getData={this.getData}/>
</div>
);
}
}
class Table extends React.Component {
// use this.props.players
}
class Create extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
ownerid: ''
};
}
onChange = (e) => {
const state = this.state
state[e.target.name] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
e.preventDefault();
const { name, ownerid } = this.state;
axios.post('http://localhost:8081/player', { name, ownerid })
.then(() => this.props.getData())
}
}
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});});
}