using findOne in mongodb to find by id - node.js

I'm making a tapTracker app with MEVN stack and there is a page with all of songs
and i want that when i click on a single song make app to open this single song only ...
IN THE FRONT END ==>
so i make route from songs.vue '{that songs page}' to viewSong.vue
<v-btn dark class="cyan darken-3" v-on:click="navigateTo({name: 'song',
params: {songId: song._id}})"> View </v-btn>
after that in viewsong.vue i make a show function with id param
<template>
<h1></h1>
</template>
<script>
import songsServices from '#/services/songsServices'
export default {
data () {
return {
song: null
}
},
async mounted () {
const songId = this.$store.state.route.params.songId
this.song = await songsServices.show(songId)
}
}
</script>
then i make an api with it to send that to back-end server in
songServices.js
show (songId) {
return Api().get(`songs/${songId}`)
}
IN THE BACK END 'SERVER' ==>
i make get http req in router.js
app.get('/songs/:songId', songsController.show)
songsController.js
async show(req,res) {
try {
const Song = await Songs.findOne({_id: req.params.songId})
res.send(song)
} catch (error) {
res.status(400).send('error: error when tring to fetch songs!!!')
console.log(error)
}
}
in postman when i make a get req with this param it give me error
where is the problem ??
hint this is the project url on github
https://github.com/mohamedAdel01/tapTracker

Related

ref.map is not a function?

this is my first post. Thank you all for the years, of assistance btw, I hope to pour in, as much as I've gotten from you guys/gals. Let's get started.
I have a Next.js / React-Redux application and here is my problem:
I'm attempting to update the Redux store, with JSON, that is returned from `fs.readFile' (the 'fs/promises' module:
//Product.js
function Product() {
const suggested_products = useSelector((state) => state.user.suggested_products) // json read from /api/products
const updateProducts = () => {
(JSON.parse(JSON.stringify(suggested_products)))?.map((product) => { // Compliler does not like this line
<div>
<input type='checkbox'>
<p> {product.category}</p>
<p>{product.service_name}</p>
</input
</div>
})
}
return (
if (userSelectedProduct) ? updateProducts() : <p>No data found</p>
}
//Form.js
import { useSWR } from 'swr'
const fetcher = (...args) => fetch(...args).then((res) => res.json());
function Form() {
const [url, setURL] = useState('');
const { data, error } = useSWR(url, fetcher);
<input
value={product}
onChange={
dispatch(updateCustomerCSP((JSON.parse(JSON.stringify(e.target.value)))));
setURL(`api/${product}/`); //Attempt to dynamically fetch data, from client side
dispatch(updateSuggestedProducts(data)); //Update data in store returned from client side fetching
}}
</input>
}
// pages/api/products
import fs from 'fs/promises';
export default function handler(req, res) {
const filePath = path.join(process.cwd(),`/data.js'); // /data.js contains JSON array [{"product-1": "value"}, {"product-2": "value"}], which is why I need to use map function.
try {
const fileData = fs.readFile(filePath);
const data = JSON.parse(JSON.stringify(fileData));
res.status(200).json(data);
} catch (err)
{
res.status(500).json({ error: 'Failed to load data' })
}
}
// This error throws ref.map is not a function from the Products.js component.
Here is the only info that I could find in regards to ref's in React.
Also, the JSON.parse and JSON.stringify wrappers, are to keep Redux happy with object going into the store. Thanks for reading community, looking forward to your input. Should any oneed more info, please let me know. Also, here is info in regards to refs, that I could find:
https://reactjs.org/docs/refs-and-the-dom.html
I figured it out. I actually had the input wrapped in a HOC, and the event handler wasn't properly registered to the input element itself., therefore failing to load in the array object into the store to use.
So be careful of that, when building your own components.
For instance,
function Component() {
function loadArrayInStore() {
loadInStore()
}
const MyButton = (props) => {
<input onChange={props.handler} // I had an inline handler here such as onChange={ (e)= { doNotLoadArrayInStoreAndDontWork()}
}
return (
<MyButton handler={loadArrayInStore} />
)
}
So be watchful, when creating HOC's :)

React - How to update my component when there is a change on the server

I want to reload the page when a put request is successful but it never reloads the page. what is the problem
async function saveEdit() {
await Axios.put('http://localhost:5000/edit', {id: id, newTitle: title, newDescription: description, newImageURL: imageURL});
window.location.reload();
}
the request works but the reload() line doesn't seem to work. or is there a better way to do this?
A simple implementation of useState() hook in react
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [data, setData] = useState(null);
async function saveEdit(id, title, description, imageURL) {
// Make sure that your request responds back with the relevant and fresh batch of data after the update
var res = await Axios.put('http://localhost:5000/edit', {id: id, newTitle: title, newDescription: description, newImageURL: imageURL});
//window.location.href = window.location.href;
var data = res.data;
setData(data)
}
return (
<div>
{data?.map(d=>{
// How you want to processes your data object.
return <h1>d.title</h1>
})}
<button onClick={()=>saveEdit(1,"Mytitle","description","test Url")}> Update </button>
</div>
);
}
For more information in react hooks refer here.

mounted method giving error message - Nuxt.js, Jest

I am new to unit testing and have a question about the mounted method inside the component.
I am testing if the button text is correctly displaying depends on one of the data values, and it passes. However, I have one method in mounted() inside the component and requests API call which is called from nuxt context.
The method is failing and consoling err message from try and catch because looks like it can not find nuxt context inside the test. This is not affecting my test but I wonder if it is fine, or do I need to fix something.
This is my component.
<template>
<button>
{{variations.length > 0 ? 'Select options' : 'add to cart'}}
</button>
</template>
<script>
data() {
return {
variations: [],
}
},
mounted() {
this.getVaridations()
},
methods: {
async getVaridations() {
try {
const variations = await this.$getVatiation.get() // this part is failing and consoling err message from catch
this.variations = variations
} catch (err) {
console.log(err) // consoling as TypeError: Cannot read properties of undefined (reading 'get')
}
},
},
</script>
This is testing
describe('Product.vue', () => {
it('btn display as "Select options" when there is validation', () => {
const wrapper = mount(Product, {})
expect(wrapper.find('.product-btn').text()).toBe('Select options') // This passes
})
})
You can mock any component methods like
import { shallowMount } from "#vue/test-utils";
describe('Product.vue', () => {
it('btn display as "Select options" when there is validation', () => {
const mocks = {
$getVatiation: {
get: () => [] // returns an empty array, change to what you want to return
}
}
const wrapper = shallowMount (Product, {mocks}) // send your mocks as an argument
expect(wrapper.find('.product-btn').text()).toBe('Select options')
})
})

Node/React/Redux: having problems passing api JSON object between Node and React

I am new to React/redux with Node. I am working on a full stack app that utilizes Node.js on the server side and React/Redux on the client side. One of the functions of the app is to provide a current and eight-day weather forecast for the local area. The Weather route is selected from a menu selection on the client side that menu selection corresponds to a server side route that performs an axios.get that reaches out and consumes the weather api (in this case Darksky) and passes back that portion of the JSON api object pertaining to the current weather conditions and the eight-day weather forecast. There is more to the API JSON object but the app consume the "current" and "daily" segment of the total JSON object.
I have written a stand-alone version of the server-side axios "get" that successfully reaches out to the Darksky API and returns the data I am seeking. I am, therefore, reasonably confident my code will correctly bring back the data that I need. My problem consists in this: when I try to render the data in my React Component, the forecast object is undefined. That, of course, means there is nothing to render.
I have reviewed my code, read a plethora of documentation and even walked through tutorials that should help me find the problem and it still eludes me. So, I am stuck and would greatly appreciate some help. Most of the comment you still in the code below will be removed after the debugging process is completed.
I am including code blocks relevant to the problem:
My React Component
// client/src/components/pages/functional/Weather.js
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import Moment from 'react-moment';
import Spinner from '../../helpers/Spinner'
import { getWeather } from '../../../redux/actions/weather'
const Weather = ({ getWeather, weather: { forecast, loading } }) => {
// upon load - execute useEffect() only once -- loads forecast into state
useEffect(() => { getWeather(); }, [getWeather])
return (
<div id='page-container'>
<div id='content-wrap' className='Weather'>
{ loading ?
<Spinner /> :
<>
<div className='WeatherHead box mt-3'>
<h4 className='report-head'>Weather Report</h4>
</div>
{/* Current Weather Conditions */}
<h6 className='current-head'>Current Conditions</h6>
<section className='CurrentlyGrid box mt-3'>
/* additional rendering code removed for brevity */
<span><Moment parse='HH:mm'>`${forecast.currently.time}`</Moment></span>
/* additional rendering code removed for brevity */
</section>
</>
}
</div>
</div>
);
};
Weather.propTypes = {
getWeather: PropTypes.func.isRequired,
weather: PropTypes.object.isRequired
};
const mapStateToProps = state => ({ forecast: state.forecast });
export default connect( mapStateToProps, { getWeather } )(Weather);
My React Action Creator
// client/src/redux/actions/weather.js
import axios from 'axios';
import chalk from 'chalk';
// local modules
import {
GET_FORECAST,
FORECAST_ERROR
} from './types';
// Action Creator
export const getWeather = () => async dispatch => {
try {
// get weather forecast
const res = await axios.get(`/api/weather`);
console.log(chalk.yellow('ACTION CREATOR getWeather ', res));
// SUCCESS - set the action -- type = GET_WEATHER & payload = res.data (the forecast)
dispatch({
type: GET_FORECAST,
payload: res.data
});
} catch (err) {
// FAIL - set the action FORECAST_ERROR, no payload to pass
console.log('FORECAST_ERROR ',err)
dispatch({
type: FORECAST_ERROR
});
};
};
My React Reducer
// client/src/redux/reducers/weather.js
import {
GET_FORECAST,
FORECAST_ERROR,
} from '../actions/types'
const initialState = {
forecast: null,
loading: true
}
export default (state = initialState, action) => {
const { type, payload } = action
switch (type) {
case GET_FORECAST:
return {
...state,
forecast: payload,
loading: false
}
case FORECAST_ERROR:
return {
...state,
forecast: null,
loading: false
}
default:
return state
}
}
My Node Route
// server/routes/api/weather.js
const express = require('express');
const axios = require('axios');
const chalk = require('chalk');
const router = express.Router();
// ***** route: GET to /api/weather
router.get('/weather', async (req, res) => {
try {
// build url to weather api
const keys = require('../../../client/src/config/keys');
const baseUrl = keys.darkskyBaseUrl;
const apiKey = keys.darkskyApiKey;
const lat = keys.locationLat;
const lng = keys.locationLng;
const url = `${baseUrl}${apiKey}/${lat},${lng}`;
console.log(chalk.blue('SERVER SIDE ROUTE FORECAST URL ', url));
const res = await axios.get(url);
// forecast -- strip down res, only using currently{} & daily{}
const weather = {
currently: res.data.currently,
daily: res.data.daily.data
};
console.log(chalk.yellow('SERVER SIDE ROUTE FORECAST DATA ', weather));
// return weather
res.json({ weather });
} catch (error) {
console.error(chalk.red('ERR ',error.message));
res.status(500).send('Server Error');
}
});
module.exports = router;
My Express server middleware pertaining to routes (just to be thorough)
// server/index.js
/* code deleted for brevity */
// define routes
app.use('/api/users', require('./routes/api/users'));
app.use('/api/auth', require('./routes/api/auth'));
app.use('/api/weather', require('./routes/api/weather'));
app.use('/api/favorites', require('./routes/api/favorites'));
/* code deleted for brevity */
If the code snippets included are not sufficient, the repo resides here: https://github.com/dhawkinson/TH12-BnBConcierge
Thank you in advance for help with this.
***** Updates *****
I notice that the console logs I have in both actions/weather.js & reducers/weather.js on the client side & routes/api/weather.js on the server side are NOT firing. That tells me that those modules must not be executing. That would explain why I am getting the error "Cannot read property 'currently' of undefined" in client/src/components/pages/functional/Weather.js. Clearly I have a missing link in this chain. I just can't see what it is.
I tried a small refactor, based on input below. I was trying to see if there was some kind of naming conflict going on. this is what I did in my React functional Component:
// client/src/components/pages/functional/Weather.js
...
const mapStateToProps = state => ({weather: { forecast: state.forecast, loading: state.loading }});
...
It didn't help.
I see that in your combineReducers here you are setting as
export default combineReducers({
alert,
auth,
weather
})
So in the store, things gets saved as { alert: {...}, auth: {...}, weather: {...}}. Can you try accessing the forecast value in your Weather as state.weather.forecast ?
const mapStateToProps = state => ({ forecast: state.weather.forecast });
Let me know if it works.
You need to modify your component.
const dispatch = useDispatch();
useEffect(() => { dispatch(getWeather()); }, [getWeather])
And your mapToStateToProps should be as follows:
const mapStateToProps = state => ({ forecast: state.weather.forecast });

How to render data received from a REST service in React Universal? (Next.js)

I want to receive data via a REST service call in my React Universal (with Next.js) app using fetch() and then render the result into JSX like this:
class VideoPage extends Component {
componentWillMount() {
console.log('componentWillMount');
fetch(path, {
method: 'get',
})
.then(response =>
response.json().then(data => {
this.setState({
video: data,
});
console.log('received');
})
);
}
render() {
console.log('render');
console.log(this.state);
if (this.state && this.state.video) {
return (
<div>
{this.state.video.title}
</div>
);
}
}
}
export default VideoPage;
Unfortunately, the output is this:
componentWillMount
render
null
received
Which does make sense because the call to fetch is asynchronously and render() finishes before the call to the REST service has finished.
In a client-side app this would be no problem because a change of state would call render() which then updates the view, but in a universal app, especially with JavaScript turned off on the client, this is not possible.
How can I solve this?
Is there a way to call the server synchronously or delay render()?
In order to get it working, I had to do 3 things:
Replace componentWillMount with getInitialProps() method
Combine fetch with await and return the data
Use this.props instead of this.state
Code looks like this now:
static async getInitialProps({ req }) {
const path = 'http://path/to/my/service';
const res = await fetch(path);
const json = await res.json();
return { video: json };
}
Then, in render() I can access the data via this.props.video, for example:
render() {
return (
<div>{this.props.video.title}</div>
);
}
You can add static async getInitialProps () {} to load data into props before the page component gets rendered.
More info here: https://github.com/zeit/next.js/blob/master/readme.md#fetching-data-and-component-lifecycle

Resources