Content disappears after refreshing the page - javascript

I have a blog app that is divided into two parts. The first part is where people can write the actual blog (title, short description, body, click on the submit button) and that blog is than displayed to the screen with all the other blogs. These blogs are clickable and can be viewed. This part works just fine. If people click on a blog they can write comments to it. It works similarly like the part where you can write the blogs (people write a comment, click on the submit button and it is displayed below the blog post). Everything is store in firebase. The problem is when I refresh the page in the comment section, everything disappears and I get no error message. If I don't refresh the comment section everything works perfect, but after refresh everything disappears, but no error message is shown.
Here are the components for the comment section:
CommentHolder is responsible for displaying the comments that are connected with the actual blog post
import React from 'react';
import { projectFirestore } from '../../firebase/config';
import DeleteComment from './DeleteComment'
class CommentHolder extends React.Component {
state = { docs: [] }
_isMounted = false;
componentDidMount = () => {
const fetchDataFromFireBase = async () => {
const getData = await projectFirestore.collection("Comments")
getData.onSnapshot((querySnapshot) => {
var documents = [];
querySnapshot.forEach((doc) => {
documents.push({ ...doc.data(), id: doc.id });
});
if (this._isMounted) {
this.setState({ docs: documents })
}
});
}
fetchDataFromFireBase()
this._isMounted = true;
}
componentWillUnmount = () => {
this._isMounted = false;
}
renderContent() {
// Delete comments
const deleteComment = async (id) => {
projectFirestore.collection('Comments').doc(id).delete().then(() => {
console.log(`Blog with id: ${id} has been successfully deleted!`)
})
}
// Build comments
let user;
if (localStorage.getItem('user') === null) {
user = [];
} else {
user = JSON.parse(localStorage.getItem('user'));
const commentArray = this.state.docs?.filter(value => value.blogID === this.props.param);
const orderedComments = commentArray.sort((a, b) => (a.time > b.time) ? -1 : (b.time > a.time) ? 1 : 0);
const renderComments = orderedComments.map(comment => {
return (
<div key={comment.id} className="card mb-3" >
<div className="card-body">
<div className="row">
<div className="col-sm">
<h6>{`${comment.name} - ${comment.time}`}</h6>
<p>{comment.comment}</p>
</div>
<div className="col-sm text-right">
{user[0].id === comment.userID ? <DeleteComment commentid={comment.id} onDeleteComment={deleteComment} /> : ''}
</div>
</div>
</div>
</div>
)
})
const updateComments = () => {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString)
const id = urlParams.get('id')
const updateComment = projectFirestore.collection('Blogs').doc(id);
return updateComment.update({
'post.comments': commentArray.length
})
}
updateComments()
return renderComments;
}
}
render() {
return (
<div>
{this.renderContent()}
</div>
)
}
}
export default CommentHolder
The AddComment contains the whole section, the text area, the submit button and the container for the comments
import React, { useState } from 'react'
import SubmitComment from './SubmitComment'
import CommentHolder from './CommentHolder';
import { useSelector, useDispatch } from 'react-redux';
const AddComment = ({ param }) => {
const [comment, setComment] = useState('');
const dispatch = useDispatch();
const state = useSelector((state) => state.state);
if(state) {
setTimeout(() => {
setComment('')
dispatch({ type: "SET_FALSE" })
}, 50)
}
return (
<div>
<div>
<div className="row">
<div className="col-sm">
<div className="form-group">
<textarea rows="4" cols="50" placeholder="Comment" className="form-control mb-3" value={comment} onChange={(e) => setComment(e.target.value)} />
</div>
</div>
</div>
</div>
<div className="mb-3">
<SubmitComment comment={comment} param={param} />
</div>
<CommentHolder param={param} />
</div>
)
}
export default AddComment
The SubmitComment is responsible for submitting the comment to the firebase
import React from 'react'
import { projectFirestore } from '../../firebase/config';
import { v4 as uuidv4 } from 'uuid';
import { useDispatch } from 'react-redux';
const SubmitComment = ({ comment, param }) => {
const dispatch = useDispatch();
const onCommentSubmit = () => {
let user;
if (localStorage.getItem('user') === null) {
user = [];
} else {
user = JSON.parse(localStorage.getItem('user'));
projectFirestore.collection('Comments').doc().set({
id: uuidv4(),
comment,
name: `${user[0].firstName} ${user[0].lastName}`,
userID: user[0].id,
blogID: param,
time: new Date().toLocaleString()
})
dispatch({ type: "SET_TRUE" });
}
}
return (
<div>
<button onClick={() => onCommentSubmit()} className='btn btn-primary'>Add comment</button>
</div>
)
}
export default SubmitComment
The DeleteComment just deletes the comment
import React from 'react'
const DeleteComment = ({ commentid, onDeleteComment }) => {
return (
<div>
<button onClick={() => onDeleteComment(commentid)} className='btn btn-outline-danger'>X</button>
</div>
)
}
export default DeleteComment
Do you guys have any suggestions on how to solve this problem? Thank you.

Related

Getting undefined when using action to find data using id [React-Redux]

I am using react redux to create a basic blogs CRUD app.
I have a blog list which have a read more button which when click should take me to that particular blog. I am trying to get into that particular blog using blog id and using useParam Hook. You can find my code below -
acion-creators - Actions
export const listBlog = (blogList) => {
return (dispatch) => {
dispatch({
type: "list-blog",
payload: blogList
})
}
}
export const addBlog = (blog) => {
return (dispatch) => {
dispatch({
type: "add-blog",
payload: blog
})
}
}
export const deleteBlog = (id) => {
return (dispatch) => {
dispatch({
type: "delete-blog",
payload: id
})
}
}
export const findBlog = (id) => {
return (dispatch) => {
dispatch({
type: "find-blog",
payload: id
})
}
}
reducer - blogReducer -
import blogs from "../data"
const reducer = (state=blogs, action) => {
if (action.type === "list-blog") {
return state
}
else if (action.type === "add-blog"){
state.push(action.payload)
return state
}
else if (action.type === "delete-blog") {
state.pop(action.payload)
return state
}
else if (action.type === "find-blog") {
for(let i=0; i<=state.length; i++){
if(state[i].id === action.payload){
console.log(state[i])
return state[i]
}
else{
return "Blog not Found"
}
}
}
else {
return state
}
}
export default reducer
Blog page which should show that selected blog after clicking read more - BlogPage.js
import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { useParams } from "react-router-dom";
import { bindActionCreators } from "redux";
import { actionCreators } from "../State/index";
export const BlogPage = () => {
const [blogId, setBlogId] = useState();
const dispatch = useDispatch();
const actions = bindActionCreators(actionCreators, dispatch)
const params = useParams()
useEffect(() => {
setBlogId(params.blogId)
},[])
const handleEdit = (id) => {
console.log(id)
const blog = actions.findBlog(id)
console.log(blog)
}
return (
<div className="container">
<h3></h3>
<p>
Body
</p>
<button className="btn btn-success my-3" onClick={() => handleEdit(blogId)}>Edit Blog</button>
<button className="btn btn-danger mx-3">Delete Blog</button>
<hr className="my-3"/>
<button className="btn btn-primary">Like</button>
<br /> <br />
<h4 className="mx-3">Comments</h4>
</div>
)
}
In BlogPage.js I am finding the selected blog Id using useParam and using that in find-blog Action to find that particular blog in my state.
State is a list of blogs stored locally.
I am getting the id when I console.log the id of the blog but I am getting undefined when I try to use actions.findBlog()
It is showing undefined when I console.log the blog I find using the findBlog action.

How can I conditionally change only one component's JSX in an array?

I have an app that allows user take and delete notes and I'm trying to implement the edit function. The problem is that I don't want to take the user to a different page, I was the note they click on to change into a form or some kind of editable space (prepopulated with the current content of the note) that they can then save so that it renders again but with the updated values (Google Keep style).
The things that I'm struggling with is how to change just one note since the notes are mapped to components through an array - I've tried using the filter() method and playing with ternary operators, but I either copy the entire array or nothing happens. I came across this question: Google Keep edit functionality, but I'm struggling to understand what's happening and how to adapt it in my code.
So the main question is: how can I change one component without disrupting the other elements in the array or their positions on the page?
Here's my Note component so far:
import React, { useState, useEffect} from "react";
import axios from "axios";
function Note(props) {
const [noteToEdit, setNoteToEdit] = useState({
title: "",
content: "",
category: ''
})
const [isEditNote, setEditNote] = useState(false)
const [idToEdit, setIdToEdit] = useState('')
function deleteNote(id) {
axios.delete(`http://localhost:5000/notes/${id}`)
.then(() => { console.log("Note successfully deleted")
props.setFetch(true)
});
}
function editNote(id, title, content, category){
setEditNote(true)
setNoteToEdit(prevNote => {
return {
title : title,
content : content,
category : category
};
});
console.log("Current note to edit after useState:")
setIdToEdit(id)
console.log(noteToEdit)
}
return (
<div>
{isEditNote && <h1>want to edit: {idToEdit}</h1>}
{!isEditNote &&
<div>
{props.notes.map((noteItem) => {
return (
<div className="note">
<h1>{noteItem.title}</h1>
<p>{noteItem.content}</p>
<button onClick={() => {editNote(noteItem._id, noteItem.title, noteItem.category, noteItem.content)}}>
Edit
</button>
<button onClick={() => {deleteNote(noteItem._id)}}>
Delete
</button>
<p>{noteItem.category}</p>
</div>
);
})}
</div>
}
</div>
)
}
export default Note
and my CreateArea component:
import React, { useState, useEffect } from "react";
import Header from "./Header";
import Footer from "./Footer";
import ListCategories from "./ListCategories";
import CreateCategory from "./CreateCategory";
import Note from "./Note";
import axios from "axios"
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
function CreateArea() {
const [isExpanded, setExpanded] = useState(false);
const [categories, setCategories] = useState([])
const [notes, setNotes] = useState([])
const [fetchB, setFetch] = useState(true)
const [fetchCategories, setFetchCategories] = useState(true)
const [noteToEdit, setNoteToEdit] = useState({
title: "",
content: "",
category: ''
})
const [ieditNote, setEditNote] = useState(false)
const [note, setNote] = useState({
title: "",
content: "",
category: ''
});
useEffect(() => {
if(fetchCategories){
fetch('http://localhost:5000/categories')
.then(res => res.json())
.then(json => {
setCategories(json)
setFetchCategories(false)
})
}
}, [fetchCategories])
useEffect(() => {
if(fetchB) {
fetch('http://localhost:5000/notes')
.then(res => res.json())
.then(json => {
console.log(json)
setNotes(json)
setFetch(false)
})
}
}, [fetchB])
function handleChange(event) {
const { name, value } = event.target;
setNote(prevNote => {
return {
...prevNote,
[name]: value
};
});
}
function submitNote(e){
e.preventDefault();
axios.post("http://localhost:5000/notes/add-note", note)
.then((res) => {
setNote({
category: '',
title: "",
content: ""
})
setFetch(true)
console.log("Note added successfully");
console.log(note)
})
.catch((err) => {
console.log("Error couldn't create Note");
console.log(err.message);
});
}
function expand() {
setExpanded(true);
}
function filterNotes(category){
fetch('http://localhost:5000/notes')
.then(res => res.json())
.then(json => {
const filtered = json.filter((noteItem) => (noteItem.category === category));
setNotes(filtered);
})
}
function editNote(id, title, content, category){
setNoteToEdit(prevNote => {
return { ...prevNote };
});
console.log("Current note to edit after useState:")
console.log(noteToEdit)
}
return (
<div>
<Header/>
<div className="categories">
<CreateCategory setFetchCategories={setFetchCategories}/>
<button className="all-button" onClick={()=>{setFetch(true)}}>All</button>
<ListCategories categories={categories} notes={notes} filterNotes={filterNotes} setFetch={setFetch}/>
</div>
<div className="notes-container">
<form className="create-note">
{isExpanded && (
<input
name="title"
onChange={handleChange}
value={note.title}
placeholder="Title"
/>
)}
<textarea
name="content"
onClick={expand}
onChange={handleChange}
value={note.content}
placeholder="Take a note..."
rows={isExpanded ? 3 : 1}
/>
<select
name="category"
onChange={handleChange}
value={note.category}>
{
categories.map(function(cat) {
return <option
key={cat.category} value={cat.value} > {cat.category} </option>;
})
}
</select>
<button onClick={submitNote}>Add</button>
</form>
<div className="notes-group">
<Note notes={notes} setFetch={setFetch} editNote={editNote} setEditNote={setEditNote}/>
</div>
</div>
<Footer/>
</div>
);
}
export default CreateArea;
Would appreciate any guidance on this, thanks!

How to fix a this react filter?

I have created a database in firebase and I have fetch it in react, that is working correctly, but I want to include a search bar to filter the elements, my problem is that when I search for an element everything works but when I delete the text from the search input the elements do not appear again.
import { db } from "../firebase";
import { Link } from "react-router-dom";
import "../App.css";
const Productos = () => {
const [productos, setProductos] = useState([]);
const getLinks = async () => {
db.collection("links").onSnapshot((querySnapshot) => {
const docs = [];
querySnapshot.forEach((doc) => {
docs.push({ ...doc.data(), id: doc.id });
});
setProductos(docs);
});
};
const handelSearch = (e) => {
const cadena = e.target.value.toLowerCase();
const limite = Productos.length;
//console.log(cadena);
let tempArray = [];
for (let i = 0; i < limite; i++) {
const etiquetas = productos[i].description.toLowerCase();
const patron = new RegExp(cadena);
const res = patron.test(etiquetas);
if (res) {
tempArray.push(productos[i]);
}
}
setProductos(tempArray);
};
useEffect(() => {
getLinks();
}, []);
return (
<>
<input
type="text"
placeholder="Buscar"
className="search"
onChange={handelSearch}
name="busqueda"
/>
<div className="productos" name="c" id="c">
<div className="grid-prod">
{productos &&
productos.map((link) => (
<div itemID={link} className="card mb-1" key={link.id}>
<div className="card-body">
<div className="d-flex justify-content-between">
<div className="contenedor-img">
<img
className="img-producto"
alt="producto"
src={link.img}
></img>
</div>
</div>
<h4 className="text-secondary titulo">{link.titulo}</h4>
<h1 className="text-secondary titulo">{link.categoria}</h1>
<Link to={"/" + link.url} rel="noopener noreferrer">
<button className="btn-prod">Ver producto</button>
</Link>
</div>
</div>
))}
</div>
</div>
</>
);
};
export default Productos;```
You can set another state array that keeps track of all the products.
ex:
const [productos, setProductos] = useState([]);
const [allProductos, setAllProductos] = useState([]);
const getLinks = async () => {
db.collection("links").onSnapshot((querySnapshot) => {
const docs = [];
querySnapshot.forEach((doc) => {
docs.push({ ...doc.data(), id: doc.id });
});
setProductos(docs);
setAllProductos(docs);
});
};
function handleSearchChange(event) {
setSearchValue(event.target.value);
search(event.target.value);
}
function search(searchValue) {
setProductos(allProductos);
if(searchValue != ""){
/* perform search logic here */
setProductos(tempArray);
}
}
Try like below, I have used test data from the JSON placeholder
And my App.js file
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Search from "./components/Search"
function App() {
return (
<div className="App">
<Search />
</div>
);
}
export default App;
Search component JS file:
import React from 'react';
class Search extends React.Component{
constructor(){
super();
this.state = {
data:'',
items: []
}
this.filterList = this.filterList.bind(this);
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then(res => res.json())
.then(
(result) => {
this.setState({data: result});
}
)
}
filterList(event){
var updatedList = this.state.data;
console.log('-----------------',updatedList)
updatedList = updatedList.filter(function(item){
return item.name.toLowerCase().search(
event.target.value.toLowerCase()) !== -1;
});
this.setState({items: updatedList});
}
componentWillMount(){
this.setState({items: this.state.data})
}
render(){
return (
<div>
<form>
<fieldset>
<input type="text" placeholder="Search" onChange={this.filterList}/>
</fieldset>
</form>
<List items={this.state.items}/>
</div>
);
}
}
class List extends React.Component{
render(){
return (
<ul>
{this.props.items &&
this.props.items.map(function(item) {
return <li key={item.name}>{item.name}</li>
})
}
</ul>
)
}
};
export default Search;

Trying to submit a user score with a button in react. Getting error message of saveScore is not a function

I am building a react application and part of the application is a quiz section. At the end of the quiz there is a button which can save the user score in the quiz to the database.
This is my express route
// #route Put api/profile/saveScore/:id
// #desc Save users quiz score to profile
// #access Private
router.put('/saveScore/:topic_id', checkObjectId('topic_id'), auth, async (req, {params: {topic_id } }, res) => {
const score = req.body.score
const topic = topic_id
const newUserTopic = {
score,
topic,
}
try {
const profile = await Profile.findOne({ user: req.user.id });
profile.topics.unshift(newUserTopic);
await profile.save();
res.json(profile)
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
})
The express route works no bother in postman so thinking the issue must be more on the react side.
This is my action route
// Save Quiz Score to users profile
export const saveScore = (topicId, payload) => async (dispatch) => {
try {
const res = await api.put(`/profile/saveScore/${topicId}`, payload);
dispatch({
type: GET_PROFILE,
payload: res.data
});
dispatch(setAlert('Topic Saved', 'success'));
} catch (err) {
const errors = err.response.data.errors;
if(errors) {
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')))
}
dispatch({
type: PROFILE_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
This is my component
import React, { useEffect, useState, Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Spinner from '../layout/Spinner';
import QuizItem from './QuizItem';
import { getTopicById } from '../../actions/topic';
import { saveScore} from '../../actions/profile';
import { SaveScoreForm } from './SaveScoreForm';
const Quiz = ({ getTopicById, saveScore, topic: { topic, loading }, match }) => {
useEffect(() => {
getTopicById(match.params.id);
}, [getTopicById, match.params.id])
const [currentIndex, setCurrentIndex] = useState(0);
const [score, setScore] = useState(0);
const [showAnswers, setShowAnswers] = useState(false)
const [formData, setFormData] = useState({ score })
const handleAnswer = (answer) => {
if(!showAnswers) {
if(answer === topic[currentIndex].correct_answer) {
setScore(score + 1);
}
}
setShowAnswers(true);
};
const handleNextQuestion = () => {
setShowAnswers(false);
setCurrentIndex(currentIndex + 1);
}
console.log(currentIndex)
const onChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value })
}
const onSubmit = (e) => {
e.preventDefault();
const payload = new FormData();
payload.append('score', formData.score)
saveScore(payload, match.params.id);
}
return topic.length > 0 ? (
<div className='container'>
{currentIndex >= topic.length ? (
<Fragment>
<SaveScoreForm topic={topic} score={score} />
<form
onSubmit={e => onSubmit(e)}
>
<input
type='hidden'
value={score}
onChange={(e) => onChange(e)}
/>
<input type='submit' className='btn btn-primary1 my-1' />
</form>
</Fragment>
) : (
<QuizItem
key={topic.question}
topic={topic[currentIndex]}
showAnswers={showAnswers}
handleNextQuestion={handleNextQuestion}
handleAnswer={handleAnswer}
/>
)}
</div>
) : (
<Spinner/>
)
}
Quiz.prototype = {
getTopicById: PropTypes.func.isRequired,
topic: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
topic: state.topic,
showAnswers: state.showAnswers,
handleNextQuestion: state.handleNextQuestion,
handleAnswer: state.handleAnswer
})
export default connect(mapStateToProps, { getTopicById })(Quiz)
Child component
import React from 'react'
export const SaveScoreForm = ({ score, topic, }) => {
return (
<div>
<div className='bg-primary1 p-2 my-4'>
<h1 className='large'>Review Your Score</h1>
<p className="lead">Quiz ended! Your score is: {(score/topic.length) * 100}%</p>
<p>Save your score to your profile or take the quiz again!</p>
</div>
</div>
);
};
export default SaveScoreForm;
TypeError: saveScore is not a function
Any help or pointers in the right direction would be very much appreciated.
Thanks
You are importing import { saveScore} from '../../actions/profile';
But then you have this prop
const Quiz = ({ getTopicById, saveScore
// ----------------------------^
which is overriding saveScore in your components context. Unless you are passing a saveScore prop while initialising <Quiz> it'll be undefined.
If you want to import the saveScore module just remove this prop variable.

Is there a way to re-render data after submit-axios post request? ReactJS

So I've recently started on learning React, where I've created a little project for me. Now on backend everythings works etc.
By now everything was going good, but now I've got stuck.
Now about the page: I've got page, where u can see details about single article, and get info about loan for price of article. I've made it on backend that default value of it is 60 months, and if u want different period, u submit other months value eg. 120. So on backend when I hit route http://localhost:8080/api/article/id i get response of data and loan is calculated with 60 months. Now if in body i send eg. {"months": 6} i get different data in response which is expected and working fine.
Now where I've hit a wall: on front end I have no idea how to update data when form is submited. Here you can see my from:
And idea is when u enter eg. 6 to lower part of page is changed:
These last two right clomuns should be changed.
Now I've tried to send with id months to the actions and then refresh page when disptach is triggered but no success - and I know that after refresh months are reseted to default value.
Now these values come from that localhost route and I'm fetching it with a axios call, and displaying content
Here is my Article.js component:
import React, { useEffect, useState, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';
import Form from 'react-validation/build/form';
import Input from 'react-validation/build/input';
import CheckButton from 'react-validation/build/button';
import ArticleService from '../services/article.service';
import { getArticle } from '../actions/articles';
const Article = (props) => {
const form = useRef();
const checkBtn = useRef();
const [content, setContent] = useState([]);
const [dataArr, setDataArr] = useState([]);
const [months, setMonths] = useState([]);
const [loading, setLoading] = useState(false);
const dispatch = useDispatch();
const onChangeMonths = (e) => {
const months = e.target.value;
setMonths(months);
};
const handleMonths = (e) => {
e.preventDefault();
setLoading(true);
if (checkBtn.current.context._errors.length === 0) {
const id = props.match.params.id;
dispatch(getArticle(id, months))
.then(() => {})
.catch(() => {
setLoading(false);
});
} else {
setLoading(false);
}
};
useEffect(() => {
const fetchPosts = async () => {
const id = props.match.params.id;
const res = await ArticleService.article(id);
setContent(res.data);
const data = res.data.kredit;
const dataArr = [];
dataArr.push({
name: 'kreditNKS-rataNKS',
price: data.kreditNKS.map((item) => {
return item;
}),
rate: data.rataNKS.map((item) => {
return item;
}),
nks: data.stopaNKS.map((item) => {
return item;
}),
banka: {
eks: data.stopaEKS.map((item) => {
return item;
}),
bankname: data.ime.map((item) => {
return item;
}),
type: data.tip.map((item) => {
return item;
}),
},
});
setDataArr(dataArr);
};
fetchPosts();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const a = dataArr;
return (
<div>
<p className='text-dark'>
<Link to='/dashboard'>
<i className='fas fa-arrow-left'></i> Nazad
</Link>
</p>
<div className='container p-3 my-3 bg-dark text-white'>
<strong>Artikal id:{content.id}</strong>
<br></br>
<br></br>
<div className='row'>
<div className='col-sm'>
Opis:
<br></br>
{content.descr}
</div>
<div className='col-sm'>
Cijena
<br></br>
{content.price}
</div>
<div className='col-sm'>
Cijena po metru kvadratnom:
<br></br>
{content.ppm2}/m2
</div>
</div>
</div>
<div className='container'>
<h3>KREDITI ZA CIJENU {content.price}</h3>
<Form onSubmit={handleMonths} ref={form}>
<div className='form-group'>
<label>Vrijeme otplate u mjesecima:</label>
<Input
type='text'
className='form-control w-25'
name='months'
value={months}
onChange={onChangeMonths}
/>
<button
className='btn btn-primary btn-block w-25'
disabled={loading}
>
{loading && (
<span className='spinner-border spinner-border-sm'></span>
)}
<span>Click</span>
</button>
<CheckButton style={{ display: 'none' }} ref={checkBtn} />
<small>
Ako se ne unese vrijeme otplate kredita, kredit se izračunava za
60 mjeseci
</small>
</div>
</Form>
</div>
<div className='container-fluid'>
<br></br>
<h4>Lista kredita</h4>
<div className='row'>
<div className='col-sm'>
<h4>Informacije o banci</h4>
{a &&
a.map((item) =>
item.banka.bankname.map((its, index) => (
<div className='card card-body flex-fill'>
<h2>{its}</h2>
<h6>EKS: {item.banka.eks[index]}%</h6>
<h6>Tip: {item.banka.type[index]} K.S</h6>
</div>
))
)}
</div>
<div className='col-sm'>
<h4>NKS</h4>
{a &&
a.map((item) =>
item.nks.map((s) => (
<div className='card card-body flex-fill'>
<h2>{s}</h2>
</div>
))
)}
</div>
<div className='col-sm'>
<h4>Ukupna cijena kredita</h4>
{a &&
a.map((item) =>
item.price.map((it2) => (
<div className='card card-body flex-fill'>
<h2>{it2} KM</h2>
</div>
))
)}
</div>
<div className='col-sm'>
<h4>Rata</h4>
{a &&
a.map((item) =>
item.rate.map((it2) => (
<div className='card card-body flex-fill'>
<h2>{it2} KM/mj</h2>
</div>
))
)}
</div>
</div>
</div>
</div>
);
};
export default Article;
actions/article.js
import { SET_MESSAGE, RATE_UPDATE, UPDATE_FAIL } from './types';
import ArticleService from '../services/article.service';
export const getArticle = (id, months) => (dispatch) => {
return ArticleService.article(id, months).then(
(response) => {
dispatch({
type: RATE_UPDATE,
});
dispatch({
type: SET_MESSAGE,
payload: response.data.message,
});
return Promise.resolve();
},
(error) => {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
dispatch({
type: UPDATE_FAIL,
});
dispatch({
type: SET_MESSAGE,
payload: message,
});
return Promise.reject();
}
);
};
services/article.service.js
import axios from 'axios';
//const API_URL = 'https://stanbackapp.azurewebsites.net/api/articles/';
const API_URL = 'http://localhost:8080/api/articles/';
//const dAPI_URL = 'https://stanbackapp.azurewebsites.net/api/article/';
const dAPI_URL = 'http://localhost:8080/api/article/';
const articles = () => {
return axios.get(API_URL);
};
const article = (id, months) => {
return axios.post(dAPI_URL + `${id}`, {
months,
});
};
export default {
articles,
article,
};
I want to frontend behave just like backend: If i don't send anything in the form display data for 60 months.(that is what is doing now), but if i type in 10 and hit click a want to page re-render these two last columns(because if you send months only them are changed) and display that new data.
Also I've tried this in dispatch:
dispatch(getArticle(id, months))
.then((response) => console.log(response))
But console.log is undefiend
Any tips? Thanks!
I think your issue may be that you are mixing state. The first time you fetch data (via useEffect), you are fetching directly via axios. However, when you fetch data in the handleMonths, you are passing the action over to Redux, which operates very differently. The other issue is that the component never retrieves the data from Redux, so any updates are essentially ignored.
My suggestion would be to use the same method for retrieving data the first time as you do subsequent times:
const handleMonths = (e) => {
...
if (checkBtn.current.context._errors.length === 0) {
const id = props.match.params.id;
try {
const res = await ArticleService.article(id, months);
... // Handle the response appropriately.
setContent(res.data);
const data = res.data.kredit;
const dataArr = [];
dataArr.push({
name: 'kreditNKS-rataNKS',
price: data.kreditNKS,
rate: data.rataNKS,
nks: data.stopaNKS,
banka: {
eks: data.stopaEKS,
bankname: data.ime,
type: data.tip,
},
});
setDataArr(dataArr);
} catch (e) {
setLoading(false);
}
} else {
setLoading(false);
}
};
This provides 2 benefits:
You can extract the method for handling the response data to make it the same for both cases.
You remove the need for an external state handler (i.e. Redux) which you may not need.

Categories