I'm trying to update the number of likes on click after success response from the server and everything works well. However, the number of likes doesn't get updated and I need to refresh the page to see the updated value on the element.
function UserPage() {
const [posts, setPosts] = useState([])
let {authTokens, user} = useContext(AuthContext)
useEffect (()=>{
const getData = async () => {
const{data: ServerResponse} = await axios.get('http://127.0.0.1:8000/api/tweets/');
setPosts(ServerResponse)
}
getData();
}, [])
const handleLike = (id)=>{
let posts_list = posts
const post_indx = posts_list.findIndex((post=> post.id==id))
posts_list[post_indx].likes
axios({
method: 'post',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' String(authTokens.access)
},
url: 'http://127.0.0.1:8000/api/tweets/action/',
data: {
id: id,
action:"like"
}
}).then(function(response){
setPosts(posts_list)
}
)
}
const handleDelete=(id)=>{
// console.log("hi")
}
return (
<div>
<NavBar className='navbar' />
{user && <p>Hello {user.username}</p>}
{
posts.map(post=>(
<SingleTweet onDelete={() => handleDelete(post.id)} numLikes={post.likes} onLike={() => handleLike(post.id)} id={post.id} content={post.content} />
))
}
</div>
);
}
Also, the SingleTweet component is as follows:
class SingleTweet extends Component {
state = { }
render() {
return (
<div className='border'>
<div className='id-ret'>
<h3>{this.props.id}</h3>
<button onClick={this.props.onLike} type="button" className="btn btn-outline-primary me-1">Retweet</button>
</div>
<p>{this.props.content}</p>
<div className='tweet-buttons'>
<div>
<button onClick={this.props.onLike} type="button" className="btn btn-primary me-1">{this.props.numLikes} Likes</button>
<button onClick={this.props.onLike} type="button" className="btn btn-outline-primary me-1">Unlike</button>
</div>
<button onClick={this.props.onDelete} type="button" >Delete</button>
</div>
</div>
);
}
}
Any suggestions would be very much appreciated
CodePudding user response:
Your state is an array. Since the object reference remains the same, React doesn't update the state thinking nothing has changed.
The reason it shows after page reload, is because you updated the same in the backend and backend returns the correct data on load which is a new object.
One way to solve your problem would be to do the following:
setPosts([...posts_list])
This will create a new array with the same data, causing the reference to change. Once the reference changes, React will know to update the state.