I want to use the package called "youtube-music-api", however I can't get it to work within React. The code resides within a React component that triggers it when the component mounts. The code I used is as follows:
const YoutubeMusicApi = require('youtube-music-api')
function fetchResults(data) {
const api = new YoutubeMusicApi()
api.initalize()
.then(info => {
api.getSearchSuggestions(data).then(result => {
console.log(result)
})
})
}
However, it ends up failing when I try to run it, I receive the following:
I tried using the package outside of React, and it performed successfully. So, I suspect that the issue may be because with React I am serving the page to the user where they then perform the API call. How might I go about using the package within React?
I suggest using the faker.js package. you can easily get fake data according your use case.
import faker from 'faker'
const [data,setData] = useState([])
useEffect(() => {
var randomName = faker.name.findName(); // Rowan Nikolaus
var randomEmail = faker.internet.email(); // Kassandra.Haley#erich.biz
var randomCard = faker.helpers.createCard(); // {avatar , name etc..}
setData({ name : randomName , email : randomEmai , card : ...randomCard })
},[]);
Related
Let's say we are creating a module called app by constructing a new vm.SourceTextModule object:
const context = {
exports: {},
console, // custom console object
};
const sandbox = vm.createContext(context);
const app = new vm.SourceTextModule(
`import path from 'path';
console.log(path.resolve('./src'));`,
{
context: sandbox,
}
);
According to the Node.js documentation to obtain the default export from path module we should "link" the imported dependencies of app module to it.
To achieve this we should pass linker callback to app.link method:
async function linker(specifier, referencingModule) {
// the desired logic...
}
await app.link(linker);
How to implement linker function properly so that we could import path module in newly created app module and use it:
await app.evaluate(); // => /home/user/Documents/project/src
P.S. We are using TypeScript, so I checked if we have installed types for path package.
package.json:
"#types/node": "^17.0.31",
I found https://github.com/nodejs/node/issues/35848 where someone posted a code snippet.
From there I've adapted the following linker callback:
const imports = new Map();
async function linker(specifier, referencingModule) {
if (imports.has(specifier))
return imports.get(specifier);
const mod = await import(specifier);
const exportNames = Object.keys(mod);
const imported = new vm.SyntheticModule(
exportNames,
() => {
// somehow called with this === undefined?
exportNames.forEach(key => imported.setExport(key, mod[key]));
},
{ identifier: specifier, context: referencingModule.context }
);
imports.set(specifier, imported);
return imported;
}
The code snippet from the GitHub issue didn't work for me on Node 18.7.0 as is, because the evaluator callback passed to the constructor of SyntheticModule is somehow called with this set to undefined. This may be a Node bug.
I also cached the imported SyntheticModules in a Map because if they have internal state, creating a new SyntheticModule every time will reset that state.
I just started learning React and so far I'm liking it. But the problem is that most of the tutorials are old and still using old states instead of hooks.
Now when I'm following a tutorial, I'm trying to convert the code I see into hooks. For now I'm really stuck and could use some help for this code. I'm trying to convert the code bellow for a functionnal component. I tried using useEffect but it didn't work.
handleChangeOrder(oldIndex, newIndex){
if (oldIndex == newIndex) {return;}
const [todos] = this.state;
let newSequence =[];
todos.forEach((todos,index)=> {
newSequence.push({id: todo.id, order: index + 1 });
});
}
-------------------------------------------
static changeTodoOrderURL(){
return apiDomain + "api/todo/reorder";
}
----------------------------------------
async changeTodoOrder(order){
const url = UrlService.changeTodoOrderUrl();
try{
const response = await HttpService.post(url,{order});
return response.data;
} catch (error){console.error("Not able to change order of the todos")};
}
What I tried so far in converting it :
function handleChangeOrder(oldIndex, newIndex) {
if (oldIndex == newIndex) {
return;
}
const todos = Array.from(todolist);
let newSequence = [];
todos.forEach((todos, index) => {
newSequence.push({id: todo.id, order: index + 1 });
});
useEffect(()=>{
axios.post('http://localhost:8000/api/todo/reorder')
.then(response=>{
setList(response.data);
console.log(response)
})
.catch(err => console.log(err));
},[])
}
I'm struggling mainly with async changeTodoOrder..
You don't need to use useEffect to send API requests based on event change, useEffect used to send API requests/perform side effect based on state change or on the mounting of the component.
Also, you can't call the hooks inside a function, by using it this way you are breaking the rules of hooks.
please review the rules of Hooks here
based on your code above from the class component you can use it as it is without using useEffect
I am wondering if i would be able to access my Svelte store values from a plain .js file.
I am trying to write functions returning a dynamic value based on a store value, to import them in any component.
But in a plain .js file I can't just access the store value with the $ sign..
Quick exemple of a basic function that uses a store value and could be used on multiple components:
//in .svelte
function add() {
$counter = $counter + 1;
}
EDIT: rephrasing a bit
EDIT:
Found a solution but i don't really know if it's really optimized..
//in .js file
import { get } from "svelte/store";
import { counter } from "./stores";
export function add() {
var counterRef = get(counter);
counter.set(counterRef + 1);
}
Yes, absolutely.
For one thing, the store API is very simple and nothing prevents you from subscribing to the store yourself to know the value:
import myStore from './stores'
myStore.subscribe(value => {
// do something with the new value
// you could store it for future reference...
})
And, if you just want to know the current value, Svelte has a helper for that, the get function:
import { get } from 'svelte/store';
import myStore from './stores'
const value = get(myStore);
In addition to rixo's answer, a better way to implement add is to use the store's update method:
import { counter } from "./stores";
export function add() {
counter.update(n => n + 1);
}
You could also create a custom store that implemented that logic.
It's not exactly what you asked for (import) but this method serves same purpose:
you pass your store as argument, so no need to import in the .js your store
import {get} from 'svelte/store'
export function add(yourStore) {
let _yourStore = get(yourStore)
yourStore.set(_yourStore + 1)
}
Then you just have to import your store in your Svelte component.
It allows not to care about store imports in your .js, but only on your component.
Many Svelte store examples don't use objects, so here's how I got it working. This uses an async fetch to update the user's locale to 0. Imagine pstats = {uid: 1, locale: 5}...
import { pstats} from './stores.js'
export async function leave_locale() {
return fetch(`./builds/leave`, {method: 'get'})
.then(res => res.json())
.then(res => {
pstats.update((theStore) => {
return Object.assign(theStore, {locale: 0});
})
})
}
I'm trying to verify that my method is correctly invoking another, imported method. For the life of me, I can't figure out how to mock the imported method using Jest.
Method I want to test
LandingPageManager.ts
import {getJSON} from './getJSON';
public fetchData(url: string) {
getJSON(url);
}
Method I want to mock
getJSON.ts
export function getJSON(url: string) {
// XHR requests logic
}
Test method
LandingPageManager.test.ts
import 'jest';
import {getJSON} from '../../../src/web/getJSON';
import {LandingPageManager} from '../../../src/web/LandingPageManager';
describe('fetchData', () => {
let manager = new LandingPageManager();
it('passes the correct URL to getJSON', () => {
const getJsonSpy = jest.mock('../../../src/web/getJSON', jest.fn());
manager.fetchData('sampleValue');
expect(getJsonSpy).toHaveBeenCalledWith('sampleValue');
getJsonSpy.restoreAllMocks();
});
});
Error I'm getting
jest.fn() value must be a mock function or spy
I've tried setting up the mock a variety of different ways. But I can't seem to get the syntax right.
Can anyone help point me in the right direction? I feel like this should be possible.
Finally figured out the answer.
Nothing needed to change in the source code (either the imported module or the class under test).
The import needed to change from:
import {getJSON} from '../../../src/web/getJSON';
to:
import * as getJSON from '../../../src/web/getJSON';
And then I was able to directly specify the function for spying with:
const jsonSpy = jest.spyOn(getJSON, 'getJSON');
Fixed test case
Here's how it all works together now.
LandingPageManager.test.ts
import 'jest';
// **** 1.) Changed the below line: ****
import * as getJSON from '../../../src/web/getJSON';
import {LandingPageManager} from '../../../src/web/LandingPageManager';
describe('fetchData', () => {
let manager = new LandingPageManager();
it('passes the correct URL to getJSON', () => {
// **** 2.) Can now specify the method for direct mocking ****
const jsonSpy = jest.spyOn(getJSON, 'getJSON');
manager.fetchData('sampleValue');
expect(jsonSpy).toHaveBeenCalledWith('sampleValue');
jest.restoreAllMocks();
});
});
I'm using react and react-router for my application on the client side. I can't seem to figure out how to get the following query parameters from a url like:
http://xmen.database/search#/?status=APPROVED&page=1&limit=20
My routes look like this (the path is totally wrong I know):
var routes = (
<Route>
<DefaultRoute handler={SearchDisplay}/>
<Route name="search" path="?status=:status&page=:page&limit=:limit" handler={SearchDisplay}/>
<Route name="xmen" path="candidate/:accountId" handler={XmenDisplay}/>
</Route>
);
My route is working fine but I'm just not sure how to format the path to get the parameters I want. Appreciate any help on this!
Note: Copy / Pasted from comment. Be sure to like the original post!
Writing in es6 and using react 0.14.6 / react-router 2.0.0-rc5. I use this command to lookup the query params in my components:
this.props.location.query
It creates a hash of all available query params in the url.
Update:
For React-Router v4, see this answer. Basically, use this.props.location.search to get the query string and parse with the query-string package or URLSearchParams:
const params = new URLSearchParams(paramsString);
const tags = params.get('tags');
The above answers won't work in react-router v4. Here's what I did to solve the problem -
First Install query-string which will be required for parsing.
npm install -save query-string
Now in the routed component you can access the un-parsed query string like this
this.props.location.search
You can cross check it by logging in the console.
Finally parse to access the query parameters
const queryString = require('query-string');
var parsed = queryString.parse(this.props.location.search);
console.log(parsed.param); // replace param with your own
So if query is like ?hello=world
console.log(parsed.hello) will log world
OLD (pre v4):
Writing in es6 and using react 0.14.6 / react-router 2.0.0-rc5. I use this command to lookup the query params in my components:
this.props.location.query
It creates a hash of all available query params in the url.
UPDATE (React Router v4+):
this.props.location.query in React Router 4 has been removed (currently using v4.1.1) more about the issue here: https://github.com/ReactTraining/react-router/issues/4410
Looks like they want you to use your own method to parse the query params, currently using this library to fill the gap: https://github.com/sindresorhus/query-string
update 2017.12.25
"react-router-dom": "^4.2.2"
url like
BrowserHistory: http://localhost:3000/demo-7/detail/2?sort=name
HashHistory: http://localhost:3000/demo-7/#/detail/2?sort=name
with query-string dependency:
this.id = props.match.params.id;
this.searchObj = queryString.parse(props.location.search);
this.from = props.location.state.from;
console.log(this.id, this.searchObj, this.from);
results:
2 {sort: "name"} home
"react-router": "^2.4.1"
Url like http://localhost:8080/react-router01/1?name=novaline&age=26
const queryParams = this.props.location.query;
queryParams is a object contains the query params: {name: novaline, age: 26}
"react-router-dom": "^5.0.0",
you do not need to add any additional module, just in your component that has a url address like this:
http://localhost:3000/#/?authority'
you can try the following simple code:
const search =this.props.location.search;
const params = new URLSearchParams(search);
const authority = params.get('authority'); //
With stringquery Package:
import qs from "stringquery";
const obj = qs("?status=APPROVED&page=1limit=20");
// > { limit: "10", page:"1", status:"APPROVED" }
With query-string Package:
import qs from "query-string";
const obj = qs.parse(this.props.location.search);
console.log(obj.param); // { limit: "10", page:"1", status:"APPROVED" }
No Package:
const convertToObject = (url) => {
const arr = url.slice(1).split(/&|=/); // remove the "?", "&" and "="
let params = {};
for(let i = 0; i < arr.length; i += 2){
const key = arr[i], value = arr[i + 1];
params[key] = value ; // build the object = { limit: "10", page:"1", status:"APPROVED" }
}
return params;
};
const uri = this.props.location.search; // "?status=APPROVED&page=1&limit=20"
const obj = convertToObject(uri);
console.log(obj); // { limit: "10", page:"1", status:"APPROVED" }
// obj.status
// obj.page
// obj.limit
Hope that helps :)
Happy coding!
After reading the other answers (First by #duncan-finney and then by #Marrs) I set out to find the change log that explains the idiomatic react-router 2.x way of solving this. The documentation on using location (which you need for queries) in components is actually contradicted by the actual code. So if you follow their advice, you get big angry warnings like this:
Warning: [react-router] `context.location` is deprecated, please use a route component's `props.location` instead.
It turns out that you cannot have a context property called location that uses the location type. But you can use a context property called loc that uses the location type. So the solution is a small modification on their source as follows:
const RouteComponent = React.createClass({
childContextTypes: {
loc: PropTypes.location
},
getChildContext() {
return { location: this.props.location }
}
});
const ChildComponent = React.createClass({
contextTypes: {
loc: PropTypes.location
},
render() {
console.log(this.context.loc);
return(<div>this.context.loc.query</div>);
}
});
You could also pass down only the parts of the location object you want in your children get the same benefit. It didn't change the warning to change to the object type. Hope that helps.
Simple js solution:
queryStringParse = function(string) {
let parsed = {}
if(string != '') {
string = string.substring(string.indexOf('?')+1)
let p1 = string.split('&')
p1.map(function(value) {
let params = value.split('=')
parsed[params[0]] = params[1]
});
}
return parsed
}
And you can call it from anywhere using:
var params = this.queryStringParse(this.props.location.search);
Hope this helps.
"react-router-dom": "6"
I could get the value of the page property by useSearchParams
let [searchParams, setSearchParams] = useSearchParams();
searchParams.get('page')
when you have a URL like http://asd.com/report/7?page=3 you can get the page . complete example is here :
import React from 'react';
import { useSearchParams} from "react-router-dom";
const Detail = (props) => {
const [searchParams, setSearchParams] = useSearchParams();
console.log('page from search',searchParams.get('page')) // 1
return (
<div></div>
);
};
export default Detail;
reactrouter
You may get the following error while creating an optimized production build when using query-string module.
Failed to minify the code from this file:
./node_modules/query-string/index.js:8
To overcome this, kindly use the alternative module called stringquery which does the same process well without any issues while running the build.
import querySearch from "stringquery";
var query = querySearch(this.props.location.search);