Get axios call in reactjs - javascript

Below is the response I am getting after doing get call:
{
    "id": “12345”,
    “details”: {
        “name”: “sample doc”,
        “market: “sample market”
    }
}
My Service Method:
ENDPOINTS = {
product: "/market/product",
}
getDetails(
id: string
): Promise<{
id: string;
}> {
const url = `${this.ENDPOINTS.PRODUCT}/${id}/name`;
return http
.get(url)
.then((response) => {
return response.data;
})
.catch((error) => {
throw error;
});
}
My component Method:
getTestingDone = () => {
this.sampleService
.getDetails(
this.props.product.id,
)
.then((response) => {
this.setState({
});
})
.catch((error) => {
console.log(error);
});
};
<TextInput
labelText="name"
type="text"
name="keyname"
value = {name}
/>
I want to print the response in this input field. Not sure How to get the response from the server to the UI. Can anyone help me with this.Do i need to make a model class? and return it in response in service method?

constructor() {
this.state = {
name: ''
}
}
getTestingDone = () => {
this.sampleService
.getDetails(this.props.product.id)
.then(({details: {name}}) => {
this.setState(state => ({...state, name}));
})
}
render() {
const { name } = this.state;
return <TextInput
labelText="name"
type="text"
name="keyname"
value = {name}/>
}

This is the correct answer for the above question:
constructor(){
this.state = {
details: {
name: "",
market: "",
}
}
getTestingDone = () => {
this.sampleService
.getDetails(this.props.product.id)
then((response) => {
this.setState({
credentials: response.credentials,
});
})
return <TextInput
labelText="name"
type="text"
name="keyname"
value = {this.state.details.name}/>
}
}

Related

Use Effect doesn't run on websocket ON

I am working on a websocket project in react. But when I send a message, the websocket does reload to display new messages. I have to reload my page manually to show the changes.
Here's my use Effect Hook
useEffect(() => {
if (socket.current) {
socket.current.on('msgSent', ({ newMsg }) => {
console.log('MESSAGE SENT', newMsg)
if (newMsg.receiver === openChatId.current) {
setMessages((prev) => [...prev, newMsg])
setChats((prev) => {
const previousChat = prev.find(
(chat) => chat.messagesWith === newMsg.receiver
)
previousChat.lastMessage = newMsg.msg
previousChat.date = newMsg.date
return [...prev]
})
}
})
}
}, [])
When I remove the useEffect dependency (i.e []), It works but it renders the message multiple times on the screen.
Here's the rest of my frontend client code
const openChatId = useRef('')
const auth = useContext(AuthContext)
const queryMessage = new URLSearchParams(search).get('message')
useEffect(() => {
if (!socket.current) {
socket.current = io(process.env.REACT_APP_API)
}
if (socket.current) {
socket.current.emit('join', { userId: auth.user._id })
socket.current.on('connectedUsers', ({ users }) => {
users.length > 0 && setConnectedUsers(users)
})
}
if (chats.length > 0 && !queryMessage) {
history.push(`/messages?message=${chats[0].messagesWith}`, undefined, {
shallow: true,
})
}
return () => {
if (socket.current) {
socket.current.emit('logout')
socket.current.off()
}
}
}, [chats])
useEffect(() => {
const getAllChats = async (token) => {
try {
setLoading(true)
const res = await getChats(token)
if (res) {
setChats(res)
setLoading(false)
}
} catch (err) {
console.log(err)
setLoading(false)
}
}
getAllChats(auth.token)
}, [])
useEffect(() => {
const loadMessages = () => {
socket.current.emit('loadMessages', {
userId: auth.user._id,
messagesWith: queryMessage,
})
socket.current.on('messagesLoaded', async ({ chat }) => {
setMessages(chat.messages)
setBannerData({
firstName: chat.messagesWith.firstName,
lastName: chat.messagesWith.lastName,
profilePicUrl: chat.messagesWith.profilePicUrl,
})
openChatId.current = chat.messagesWith._id
})
socket.current.on('noChatFound', async () => {
const { firstName, lastName, profilePicUrl } = await ChatGetUserInfo(
queryMessage,
auth.token
)
setBannerData({ firstName, lastName, profilePicUrl })
setMessages([])
openChatId.current = queryMessage
})
}
if (socket.current) {
loadMessages()
}
}, [queryMessage])
const sendMsg = (msg) => {
if (socket.current) {
socket.current.emit('sendNewMsg', {
userId: auth.user._id,
msgSendToUserId: openChatId.current,
msg,
})
}
}
The backend works very well. U think my problem is with the useEffect
I fixed it. I was missing the [chats] dependency

Changing class component to functional component

Need to change this class component code into functional component, what are the required changes for converting this class component to functional component. Please check the code for the changes. I am more into using functional components, so I want this code to be converted to functional component
class MTS extends React.Component {
constructor(props) {
super(props);
this.state = {
message:null,
msgStatus: null,
version :null ,
data: [],
clusters:null
};
this.receiveData = this.receiveData.bind(this);
}
//************************************************************************
onGetAPI=()=>{
var _self = this;
fetch('http://127.0.0.1/api/v1/version')
.then(response =>
{
this.setState({ msgStatus : response.status, strStatusText : response.statusText }) // console.log(this.msgStatus) ;
return response.json();
})
.then(data => this.setState({ version : data }))
.then(function(json) {
console.log(json);
_self.receiveData(json);
});
}
//*************************************************************************
onGetClusters=()=>{
<label>Cluster ID <input style={{backgroundColor: "lightgray"}} type = "textarea" ref ="input"></input></label>
var _self = this;
fetch('http://127.0.0.1/api/v1/clusters')
.then(response =>
{
this.setState({ msgStatus : response.status , strStatusText : response.statusText}) // console.log(this.msgStatus) ;
return response.json();
})
//.then(data => this.setState({ clusters : data })
.then(function(json) {
console.log(json);
_self.receiveData(json);
} );
}
//*************************************************************************
receiveData(data) {
this.setState({data});
}
//*************************************************************************
onGetClustersID=()=>{
var _self1 = this;
let clusterinfo = this.refs.input.value;
//let clusterinfo1 =JSON.parse(clusterinfo);
console.log(clusterinfo);
fetch(' http://127.0.0.1/api/v1/clusters/'+ clusterinfo)
.then(response =>
{
this.setState({ msgStatus : response.status, strStatusText : response.statusText }) // console.log(this.msgStatus) ;
return response.json();
})
//.then(data => this.setState({ clusters : data })
.then(function(json) {
console.log(json);
_self1.receiveData(json);
} );
}
render(){
return(
<h4>Response status : {this.state.msgStatus} {this.state.strStatusText}</h4>
<h4> Output : {JSON.stringify(this.state.data)}</h4>
)
};
}
Here you are
// 1. create a function called MTS
import { useState } from 'react'
const MTS = () => {
// 2. using `useState`
const [state, setState] = useState({
message:null,
msgStatus: null,
version :null ,
data: [],
clusters:null
})
// 3. convert all method to lambda function
// remove var _self = this;
// replace this.setState => setState
// replace _self.receiveData => receiveData
const onGetAPI = ()=> {
fetch('http://127.0.0.1/api/v1/version')
.then(response =>
{
setState({ msgStatus : response.status, strStatusText : response.statusText }) // console.log(this.msgStatus) ;
return response.json();
})
.then(data => setState({ version : data }))
.then(function(json) {
console.log(json);
receiveData(json);
});
}
const receiveData = (data) => {
setState({data});
}
const onGetClusters = () => {
<label>Cluster ID <input style={{backgroundColor: "lightgray"}} type = "textarea" ref ="input"></input></label>
fetch('http://127.0.0.1/api/v1/clusters')
.then(response =>
{
setState({ msgStatus : response.status , strStatusText : response.statusText}) // console.log(this.msgStatus) ;
return response.json();
})
.then(function(json) {
console.log(json);
receiveData(json);
} );
}
const onGetClustersID = () => {
// let clusterinfo = this.refs.input.value;
// let clusterinfo1 =JSON.parse(clusterinfo);
console.log(clusterinfo);
fetch(' http://127.0.0.1/api/v1/clusters/'+ clusterinfo)
.then(response =>
{
setState({ msgStatus : response.status, strStatusText : response.statusText })
return response.json();
})
.then(function(json) {
console.log(json);
receiveData(json);
} );
}
return (
<h4>Response status : {state.msgStatus} {state.strStatusText}</h4>
<h4> Output : {JSON.stringify(state.data)}</h4>
)
}

How to display this data from console.log(element.faculty_name) to template in vue?

I have the function of display data from major table on MySQL. I want to display the type of that major by comparing with the id of the faculty table like below. I have it displayed on console.log, how do I display it on the template?
Template tag
<td>
{{ filterFaculty }}
</td>
Script tag
data() {
return {
majors:[],
faculties:[],
form: new Form({
major_id:'',
major_code:'',
major_name:'',
major_faculty:'',
major_status: '',
}),
};
},
computed: {
filterFaculty() {
for(let i in this.majors) {
this.faculties.forEach((element) => {
if(element.faculty_code==this.majors[i].major_faculty) {
console.log(element.faculty_name);
}else {
return '-';
}
});
}
}
},
mounted() {
this.fetchFaculties();
this.fetchMajors();
},
methods: {
fetchFaculties(page_url) {
let vm = this;
page_url = '../../api/admin/edu-faculty/faculty/faculty';
fetch(page_url)
.then(res => res.json())
.then(res => {
this.faculties = res.data;
})
.catch(err => console.log(err));
},
fetchMajors(page_url) {
let vm = this;
page_url = '../../api/admin/edu-major/major/'+this.currentEntries+'?page='+this.pagination.current_page;
fetch(page_url)
.then(res => res.json())
.then(res => {
this.majors = res.data;
this.pagination = res.meta;
})
.catch(err => console.log(err));
},
}
There are different ways to achieve that, I think the easiest is to do following:
Define something in your data - like inputText and than set your element.faculty_name to this - like following:
data() {
return {
inputText: "",
}
}
computed: {
filterFaculty() {
for(let i in this.majors) {
this.faculties.forEach((element) => {
if(element.faculty_code==this.majors[i].major_faculty) {
this.inputText = element.faculty_name; //Changed here
}else {
return '-';
}
});
}
}
},
and than reference it in your template like this:
<td>
{{ inputText }}
</td>
This should solve your problem!

Cannot read property 'conversationId' of undefined while using a reducer function

Just to make it clear router uses the code below and my messages.js are inside api folder....
router.use("/messages", require("./messages"));
so my api call is correct.
Backend for posting the message.... I know conversationId will be null if no conversation exists but... I am trying to send message where conversation exists already and still I am getting cannot read the conversationId of undefined....
// expects {recipientId, text, conversationId } in body
// (conversationId will be null if no conversation exists yet)
router.post("/", async (req, res, next) => {
try {
if (!req.user) {
return res.sendStatus(401);
}
const senderId = req.user.id;
const { recipientId, text, conversationId, sender } = req.body;
// if we already know conversation id, we can save time and just add it to message and return
if (conversationId) {
const message = await Message.create({ senderId, text, conversationId });
return res.json({ message, sender });
}
// if we don't have conversation id, find a conversation to make sure it doesn't already exist
let conversation = await Conversation.findConversation(
senderId,
recipientId
);
if (!conversation) {
// create conversation
conversation = await Conversation.create({
user1Id: senderId,
user2Id: recipientId,
});
if (onlineUsers.includes(sender.id)) {
sender.online = true;
}
}
const message = await Message.create({
senderId,
text,
conversationId: conversation.id,
});
res.json({ message, sender });
} catch (error) {
next(error);
}
});
module.exports = router;
This is the frontend that posts the data to the backend....
const saveMessage = async (body) => {
const { data } = await axios.post("/api/messages", body);
return data;
};
Okay so here is detail information on how I am dispatching it.
class Input extends Component {
constructor(props) {
super(props);
this.state = {
text: "",
};
}
handleChange = (event) => {
this.setState({
text: event.target.value,
});
};
handleSubmit = async (event) => {
event.preventDefault();
// add sender user info if posting to a brand new convo,
// so that the other user will have access to username, profile pic, etc.
const reqBody = {
text: event.target.text.value,
recipientId: this.props.otherUser.id,
conversationId: this.props.conversationId,
sender: this.props.conversationId ? null : this.props.user,
};
await this.props.postMessage(reqBody);
this.setState({
text: "",
});
};
render() {
const { classes } = this.props;
return (
<form className={classes.root} onSubmit={this.handleSubmit}>
<FormControl fullWidth hiddenLabel>
<FilledInput
classes={{ root: classes.input }}
disableUnderline
placeholder="Type something..."
value={this.state.text}
name="text"
onChange={this.handleChange}
/>
</FormControl>
</form>
);
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(withStyles(styles)(Input));
const mapDispatchToProps = (dispatch) => {
return {
postMessage: (message) => {
dispatch(postMessage(message));
},
};
};
// message format to send: {recipientId, text, conversationId}
// conversationId will be set to null if its a brand new conversation
export const postMessage = (body) => (dispatch) => {
try {
const data = saveMessage(body);
if (!body.conversationId) {
dispatch(addConversation(body.recipientId, data.message));
} else {
dispatch(setNewMessage(data.message));
}
sendMessage(data, body);
} catch (error) {
console.error(error);
}
};
So I have attached what I want to do here now....
But I am still getting the problem....
// CONVERSATIONS THUNK CREATORS, this is how I am getting data from the backend
export const fetchConversations = () => async (dispatch) => {
try {
const { data } = await axios.get("/api/conversations");
dispatch(gotConversations(data));
} catch (error) {
console.error(error);
}
};
export const setNewMessage = (message, sender) => {
return {
type: SET_MESSAGE,
payload: { message, sender: sender || null },
};
};
// REDUCER
const reducer = (state = [], action) => {
switch (action.type) {
case GET_CONVERSATIONS:
return action.conversations;
case SET_MESSAGE:
return addMessageToStore(state, action.payload);
case ADD_CONVERSATION:
return addNewConvoToStore(
state,
action.payload.recipientId,
action.payload.newMessage
);
default:
return state;
}
};
I am getting an error saying Cannot read property 'conversationId' of undefined while using a reducer function... Should I give the setintial value of the message to empty?
export const addMessageToStore = (state, payload) => {
const { message, sender } = payload;
// if sender isn't null, that means the message needs to be put in a brand new convo
if (sender !== null) {
const newConvo = {
id: message.conversationId,
otherUser: sender,
messages: [message],
};
newConvo.latestMessageText = message.text;
return [newConvo, ...state];
}
return state.map((convo) => {
if (convo.id === message.conversationId) {
const convoCopy = { ...convo };
convoCopy.messages.push(message);
convoCopy.latestMessageText = message.text;
return convoCopy;
} else {
return convo;
}
});
};
Issue
The saveMessage function is declared async
const saveMessage = async (body) => {
const { data } = await axios.post("/api/messages", body);
return data;
};
but the postMessage action creator isn't async so it doesn't wait for the implicitly returned Promise to resolve before continuing on and dispatching to the store. This means that data.message is undefined since a Promise object doesn't have this as a property.
export const postMessage = (body) => (dispatch) => {
try {
const data = saveMessage(body); // <-- no waiting
if (!body.conversationId) {
dispatch(addConversation(body.recipientId, data.message));
} else {
dispatch(setNewMessage(data.message));
}
sendMessage(data, body);
} catch (error) {
console.error(error);
}
};
Solution
Declare postMessage async as well and await the data response value.
export const postMessage = (body) => async (dispatch) => {
try {
const data = await saveMessage(body); // <-- await response
if (!body.conversationId) {
dispatch(addConversation(body.recipientId, data.message));
} else {
dispatch(setNewMessage(data.message));
}
sendMessage(data, body);
} catch (error) {
console.error(error);
}
};

Not triggered catch from action

I have action that always returns Promise.reject:
module.exports = { create: createActionAsync('CREATE_USER', () => {
return Promise.reject({
response: {
type: 'error',
message: 'It will be implemented soon',
},
});
})}
But in component catch block doesn't work:
onAddUser(data) {
const { userActions: { create } = {} } = this.props;
create(data)
.then(() => {})
.catch(err => console.error(err)) // not working

Categories