Getting results from Yandex translate - reactjs

This is kind of a silly question, but I am using the Yandex API to translate words from Spanish to English, by pasing the spanish word/phrase into a function. However, I do not know how to actually return the translation from the function! How can I get my changeString method to return the res.text[0]?
import React, { Component } from "react";
class Display extends Component {
render() {
return (
<div>
<button> {this.changeString(this.props.translation)} </button>
</div>
);
}
changeString = spanishText => {
var output = null;
var translate = require("yandex-translate")(
"API KEY"
);
translate.translate(spanishText, { to: "en" }, function(err, res) {
console.log(res.text)
});
};
}
export default Display;

You can set it in the state and update it to trigger the rerender. Like the following
import React, { Component } from "react";
class Display extends Component {
constructor(props) {
super(props);
this.state = { theWord: '' };
}
componentDidMount() {
var output = null;
var translate = require("yandex-translate")(
"API KEY"
);
translate.translate('spanishText',{ to: "en" }, (err, res) => {
this.setState({theWord: res});
});
}
render() {
return (
<div>
<button> {this.state.theWord} </button>
</div>
);
}
}
export default Display;

Related

Play songs one after another with Howler and NextJS

I have a list of songs on github, the goal is to play all songs one by one and post messages in console. But I faced a problem, how to find if the song is finished? Otherwise my code tries to play all songs without waiting the song's end.
import { Howl } from 'howler'
import { useState } from 'react'
export default function PlaySound() {
let [initSong, updatedSong] = useState(0)
const songs = [
'https://raw.githubusercontent.com/Sound/master/play1.mp3',
'https://raw.githubusercontent.com/Sound/master/play2.mp3',
'https://raw.githubusercontent.com/Sound/master/play3.mp3',
'https://raw.githubusercontent.com/Sound/master/play4.mp3',
'https://raw.githubusercontent.com/Sound/master/play5.mp3',
]
var sound = new Howl({
src: songs[initSong],
})
function postAMessage() {
for (let i = 0; i < songs.length; i++) {
if (initSong >= songs.length) return
console.log('New song ' + i)
sound.play()
updatedSong(initSong++)
i++
}
}
return (
<div>
<button onClick={postAMessage}>Play</button>
</div>
)
}
can you try react-Howler
import React from "react";
import ReactHowler from "react-howler";
import Button from "../components/Button";
class OnlyPlayPauseButton extends React.Component {
constructor(props) {
super(props);
this.state = {
playing: false
};
this.handlePlay = this.handlePlay.bind(this);
this.handlePause = this.handlePause.bind(this);
}
handlePlay() {
this.setState({
playing: true
});
}
handlePause() {
this.setState({
playing: false
});
}
render() {
return (
<div>
<ReactHowler
src={["sound.ogg", "sound.mp3"]}
playing={this.state.playing}
/>
<Button onClick={this.handlePlay}>Play</Button>
<Button onClick={this.handlePause}>Pause</Button>
</div>
);
}
}
export default OnlyPlayPauseButton;
refer: https://www.npmjs.com/package/react-howler

Undefined props in componentDidMount

This is starting to get really frustrating. Basically, I cannot access props in my subcomponents. if I try to render them directly using this.props- it works, but if I need to do additional processes with them, or save them into state, I get undefined props all the time. I have a parent component, which looks something like this:
import React from 'react';
import Title from './EventSubComponents/Title';
import SessionInfo from './EventSubComponents/SessionInfo';
import SessionTime from './EventSubComponents/SessionTime';
import Location from './EventSubComponents/Location';
import Subscribers from './EventSubComponents/Subscribers';
class EventNode extends React.Component {
constructor(props) {
super(props);
this.state = {
'event': [],
}
}
componentDidMount() {
this.getEvent(this.props.location.selectedEventId);
}
getEvent(eventId) {
fetch('/api/v.1.0/event/' + eventId, {mode: 'no-cors'})
.then(function(response) {
if(!response.ok) {
console.log('Failed to get single event.');
return;
}
return response.json();
})
.then((data) => {
if (!data) {
return;
}
this.setState({
'event': data
})
});
}
render() {
return(
<div className="event-wrapper">
<Title
title = { this.state.event.title }
date = { this.state.event.start }
/>
<SessionInfo
distance = { this.state.event.distance }
type = { this.state.event.type }
/>
<SessionTime
start = { this.state.event.start }
end = { this.state.event.end }
/>
<Location location = { this.state.event.start_location }/>
<Subscribers
subscribers = { this.state.event.subscribers }
eventId = { this.state.event._id }
/>
</div>
);
}
}
export default EventNode;
And my sub-component SessionTime, which looks like this:
import React from 'react';
import moment from 'moment';
class Title extends React.Component {
constructor(props) {
super(props);
this.state = {
'title': '',
'date': '',
}
}
componentDidMount() {
console.log(this.props.title);
console.log(this.props.date);
// undefined both props.
this.convertToTitleDate(this.props.date);
this.setState({
'title': this.props.title
})
}
convertToTitleDate(date) {
var newDate = moment(date).format('dddd, Do MMMM')
this.setState({
'date': newDate,
});
}
render() {
return (
<div className="event-title-wrapper">
<h1> { this.state.title } </h1>
<div className="event-title-date"> { this.state.date } </div>
</div>
);
}
}
export default Title;
Could anyone explain, why both this.props.date and this.props.title are undefined in my componentDidMount function? I have couple more components in my EventNode and I have the same problems in them as well.
Changing componentDidMount to componentWillMount does not help. I am fairly certain I have problems in my parent EventNode component, but I cannot figure out where. Inside EventNode render() all the state variables are defined.
You initialize event to an empty array and pass down this.state.event.start and this.state.event.end to SessionTime, which will both be undefined on first render since event has not been loaded yet and there are no start and end properties on the array.
You could instead e.g. set event to null initially, and return null from the render method until the event has been loaded.
Example
class EventNode extends React.Component {
state = {
event: null
};
// ...
render() {
const { event } = this.state;
if (event === null) {
return null;
}
return (
<div className="event-wrapper">
<Title title={event.title} date={event.start} />
<SessionInfo distance={event.distance} type={event.type} />
<SessionTime start={event.start} end={event.end} />
<Location location={event.start_location} />
<Subscribers
subscribers={event.subscribers}
eventId={this.state.event._id}
/>
</div>
);
}
}

Unable to read params property from query string?

I have a simple app that access the opentable api (http://opentable.herokuapp.com/api/restaurants). My app, when loaded, simply displays content specified from the query parameters. For example, appending ?city=toronto would give me all restaurants in Toronto. Here is a working, hardcoded example:
import React, { Component } from "react";
import Spinner from "./components/common/Spinner";
class App extends Component {
constructor(props) {
super(props);
this.state = {
items: [],
isLoading: false
};
}
componentDidMount() {
// // let city = this.props.match.params.city;
// // console.log(city);
// console.log(this.props.match.params.city);
fetch("http://opentable.herokuapp.com/api/restaurants?city=Toronto")
.then(res => res.json())
.then(json => {
this.setState({
isLoading: true,
items: json
});
});
}
render() {
const { isLoading, items } = this.state;
let itemsToArray = Object.values(items);
return !isLoading ? (
<div>
<Spinner />
</div>
) : (
<div className="App">
<ul>
{itemsToArray[3].map(item => (
<div>
<li key={item.id}>{item.name}</li>
</div>
))}
</ul>
</div>
);
}
}
export default App;
If I were to uncomment console.log(this.props.match.params.city);, it tosses an error TypeError: Cannot read property 'params' of undefined. Am I accessing the params incorrectly? I'd like to do something like,
componentDidMount() {
let city = this.props.match.params.city;
fetch(`http://opentable.herokuapp.com/api/restaurants?city=${city}`)
.then(...
If you are trying to use something like:
http://myapp/page?city=Toronto
Then, this.props.match.params.city won't work. The reason being, the use-case of match.params.city is supposed to be in the Routes.
import { Route } from "react-router-dom";
<Route path="/path/:city" component={App} />
In your componentDidMount() lifecycle method, try using:
const urlParams = new URLSearchParams(window.location.search);
let city = urlParams.get('city');
For the above code, have a look at How can I get query string values in JavaScript? In your code, if you try logging the value of city, it might be undefined if you haven't configured your route this way.
Sample Code
class App extends React.Component {
state = {
city: "None"
};
componentDidMount() {
const urlParams = new URLSearchParams(window.location.search);
let city = urlParams.get("city");
this.setState({
city
});
console.log(city);
}
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<h3>You are in {this.state.city}!</h3>
</div>
);
}
}
Working Demo: CodeSandbox
You can use this function to access the URL params
var getParams = function (url) {
var params = {};
var parser = document.createElement('a');
parser.href = url;
var query = parser.search.substring(1);
var vars = query.split('&');
if(vars == ''){
params = '';
return params;
}
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
params[pair[0]] = decodeURIComponent(pair[1]);
}
return params;
};
and call it
console.log(getParams(window.location.href));
What if you try to wrap your App Class component with withRouter? so, it will look like the following:
import React, { Component } from "react";
import { withRouter } from 'react-router-dom';
import Spinner from "./components/common/Spinner";
class App extends Component {
//....
}
export default withRouter(App);

trying to pass my arrays (props) into my publish function as selector

import { Mongo } from 'meteor/mongo';
import { Meteor } from 'meteor/meteor';
import React, {Component} from 'react';
import {check} from 'meteor/check';
export const Adressen = new Mongo.Collection('Phonebook');
if (Meteor.isServer) {
Meteor.publish('ArrayToExport', function(branches) {
check(branches, [Match.Any]);
if(branches.length > 10){
return this.ready()
};
return Adressen.find(
{branche: {$in: branches}}, {fields: {firmenname:1, plz:1}}
);
});
}
.
import React, { Component } from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import {Adressen} from "../api/MongoDB";
class ExportArray extends Component{
constructor(props){
super(props);
this.state = {
branches: this.props.filteredBranches
};
}
render(){
return(
<div>
<button onClick={this.exportArrays}></button>+
</div>
);
}
}
export default withTracker( (branches) => {
Meteor.subscribe('ArrayToExport', branches);
return {
ArrayToExport: Adressen.find({}).fetch()
};
})(ExportArray);
this.props.filteredBranche is a pure array,generated through controlled input field. this.props.filteredBranches changes as Input changes, in parent Component.
I thought I was sending my this.props.filteredBranches as an argument through withTracker function. But nothing is passed to the publish function.
if (Meteor.isServer) {
arrayExfct = function (array){
return {
find: {branche:{$in: array }},
fields: {firmenname:1, plz:1}
};
}
Meteor.publish('ArrayToExport', function (array) {
return Adressen.find(
arrayExfct(array).find, arrayExfct(array).fields);
});
}
.
export default withTracker( () => {
arrayExfct = function(array) {
return {
find: {branche: {$in: array}},
fields: {firmenname:1, plz:1}
}
}
var array = ['10555'];
Meteor.subscribe('ArrayToExport', array );
var arrayExfct = Adressen.find(arrayExfct(array).find, arrayExfct(array).fields);
return {
ArrayToExport: Adressen.find({}).fetch()
};
})(ExportArray);
It would help if you also added an example of where you used this component and how you pass props to it, but I think I see your problem.
You expect the local state in your rendering component to get into the withTracker container, but that would be the other way around. When you make the withTracker container, you are really making another react component that renders your display component (ExportArray) and passes the data (ArrayToExport) down into it.
So, props go like this currently:
external render -> withTracker component -> ExportArray
What you need to do it to get the filteredBranches (which you pass from a parent component?) from the props argument in withTracker and pass that to the subscribtion,
class ExportArray extends Component{
exportArrays () {
const { ArrayToExport } = this.props;
}
render(){
const { ArrayToExport } = this.props;
return(
<div>
<button onClick={this.exportArrays}></button>+
</div>
);
}
}
export default withTracker(propsFromParent => {
const { filteredBranches } = propsFromParent;
Meteor.subscribe('ArrayToExport', filteredBranches);
return {
ArrayToExport: Adressen.find({}).fetch()
};
})(ExportArray);
Hi the issue is with the code below. The parameter called branches is the props so branches.branches is the array you passed in.
export default withTracker( (branches) => {
Meteor.subscribe('ArrayToExport', branches);
return {
ArrayToExport: Adressen.find({}).fetch()
};
})(ExportArray);
Try the following.
export default withTracker( ({branches}) => {
Meteor.subscribe('ArrayToExport', branches);
return {
ArrayToExport: Adressen.find({}).fetch()
};
})(ExportArray);
Notice all that changed was
(branches)
became
({branches})
I solved my problem with a combination of Session Variables and State.
//Client
import React, { Component } from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import {Adressen} from "../api/MongoDB";
import {Meteor} from 'meteor/meteor';
import { Session } from 'meteor/session';
class ExportArray extends Component{
constructor(){
super();
this.state = {
x: [],
y: []
};
this.exportArrays = this.exportArrays.bind(this);
}
exportArrays(e){
e.preventDefault();
this.setState({x: this.props.filteredBranches});
this.setState({y: this.props.filteredPostleitzahlen});
}
render(){
var selector = {branche: {$in: this.state.x},plz: {$in: this.state.y}};
Session.set('selector', selector);
return(
<div>
<button onClick={this.exportArrays}> Commit </button>
</div>
);
}
}
export default withTracker( () => {
const ArrayfürExport = Meteor.subscribe('ArrayToExport', Session.get('selector') );
return {
ArrayToExport: Adressen.find({}).fetch()
};
})(ExportArray);
//Server
Meteor.publish('ArrayToExport', function (selector) {
console.log('von mongodb', selector);
return Adressen.find(
selector
, {
fields: {firmenname:1, plz:1}
});
});
}

Passing a function in props to a component

I'm new to react and trying to pass a global function to components to avoid repeating it in each of them. That doesn't work, I get an undefined error when I try to call it in the components.
Here is my code :
import React from 'react';
//components
import League from './League';
class App extends React.Component {
state = {
leagues: {},
};
componentDidMount() {
this.getLeagues();
}
get(url) {
var myHeaders = new Headers();
myHeaders.append("Accept", "application/json");
myHeaders.append("X-Mashape-Key", "mysecretkeyblablabla");
var myInit =
{
headers: myHeaders
};
return fetch(url,myInit)
.then(function(response) {
if(response.ok) {
return response.json().then(function(json) {
return json.data;
});
}
});
};
getLeagues() {
this.get('https://sportsop-soccer-sports-open-data-v1.p.mashape.com/v1/leagues').then((data) => {
this.setState({leagues: data.leagues});
});
}
render() {
const leagues = Object
.keys(this.state.leagues)
.map(key => <League get={this.get} key={key} details={this.state.leagues[key]} />
);
return(
<div className="App">
<div className="App-header">
<h1>Welcome to Foot Stats app (made in ReactJS)</h1>
</div>
<p className="App-intro">
Here is the place where I should put the countries.
</p>
<ul>
{leagues}
</ul>
</div>
);
};
}
export default App;
and my League component
import React from 'react';
import Season from './Season';
class League extends React.Component {
state = {
seasons: {},
};
constructor(props) {
super(props);
}
componentDidMount() {
//this.getSeasonsAvailable(this.props.details.league_slug);
}
getSeasonsAvailable(league) {
const url = 'https://sportsop-soccer-sports-open-data-v1.p.mashape.com/v1/leagues/{league_slug}/seasons'.replace('{league_slug}',league);
const seasons = [];
console.log(this.props);
this.props.get(url).then((data) => {
data.seasons.map(function(object, i) {
seasons[data.seasons[i].identifier] = data.seasons[i];
});
this.setState({seasons: seasons});
});
};
render() {
const seasons = Object
.keys(this.state.seasons)
.map(key => <Season key={key} league_slug={this.props.details.league_slug} details={this.state.seasons[key]} />
);
return (
<li>
<span onClick={this.getSeasonsAvailable.bind(this.props.details.league_slug)}>{this.props.details.nation} : {this.props.details.name}</span>
<ul>
{seasons}
</ul>
</li>
);
}
static propTypes = {
get: React.PropTypes.func.isRequired
};
}
export default League;
When I click on the season component, I get this error :
Cannot read property 'get' of undefined
And my console.log(this.props) returns me undefined.
Thanks !
You just need to change
<span onClick={this.getSeasonsAvailable.bind(this.props.details.league_slug)}>
to
<span onClick={this.getSeasonsAvailable.bind(this, this.props.details.league_slug)}>
Apart from this, if you want to use ES6 way to do this. You can use arrow functions
<span onClick={() => this.getSeasonsAvailable(this.props.details.league_slug)}>
or you can bind the function getSeasonsAvailable in the constructor using
constructor() {
super();
this.getSeasonsAvailable = this.getSeasonsAvailable.bind(this);
}
You can read in more detail about it here and here.
Because your onClick: .bind(this.props.details.league_slug)
what is this.props.details.league_slug actually?
bind will change the reference of this in getSeasonsAvailable (this will ref to this.props.details.league_slug, I don't know what it is), of course you will get undefined when you call this.props
Try just .bind(this), so the this in getSeasonsAvailable can ref to the component itself.

Resources