React.js translate component not showing on the browser - javascript

I am trying to create a web app in which user search for a word using 'Form' component and then the result is fetched from an API and then passed to 'translate' component, but my 'translate' component is not showing in the browser.
form.jsx
import React from "react";
import "./form.scss";
import Translate from "./translate"
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
term: "",
getdata: []
}
}
handleChange = (e) => {
e.preventDefault();
this.setState({ [e.target.name]: e.target.value });
};
componentDidMount() {
}
submit = (e) => {
e.preventDefault();
const { term } = this.state;
const rawUrl="https://mashape-community-urban-dictionary.p.rapidapi.com/define?term="+term;
const url=rawUrl;
fetch(url, {
"method": "GET",
"headers": {
"x-rapidapi-host": "mashape-community-urban-dictionary.p.rapidapi.com",
"x-rapidapi-key": "c8cb6b8cccmshc02b57f0b5a8c98p1516cdjsnb64d72a5ad33"
}
})
.then(response => {
return response.json();
})
.then(data=>{
this.setState({getdata:[data.list]});
console.log(this.state.getdata);
})
.catch(err => {
console.log(err);
});
}
render() {
const translate=this.state.getdata.map(item => (<Translate word={item.word} definition={item.definition} />))
return (
<div class="full">
{translate}
<div class="searchForm">
<form>
<input type="text" name="term" value={this.state.term} placeholder="Enter a word here" onChange={this.handleChange}></input><button onClick={this.submit}>Search</button>
</form>
</div>
</div>
);
}
}
export default Form;
translate.jsx
import React from "react";
import "./translate.css";
class Translate extends React.Component {
render() {
return (
<div class="all">
<div class="single">
<div class="word">
{this.props.word}
</div>
<div class="def">
{this.props.definition}
</div>
</div>
</div>
);
}
}
export default Translate;
Can anyone solve this error.
I am stuck on this for a long time.

The issue is that you're saving the array returned by the API call within another array this.setState({getdata:[data.list]});. This is making it difficult to parse. Below is a working example which has been simplified due to limited access to your css files:
Form.js
import React from "react";
import Translate from "./Translate";
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
term: "",
getdata: []
};
}
handleChange = (e) => {
e.preventDefault();
this.setState({ [e.target.name]: e.target.value });
};
componentDidMount() {}
submit = (e) => {
e.preventDefault();
const { term } = this.state;
const rawUrl =
"https://mashape-community-urban-dictionary.p.rapidapi.com/define?term=" +
term;
const url = rawUrl;
fetch(url, {
method: "GET",
headers: {
"x-rapidapi-host": "mashape-community-urban-dictionary.p.rapidapi.com",
"x-rapidapi-key": "c8cb6b8cccmshc02b57f0b5a8c98p1516cdjsnb64d72a5ad33"
}
})
.then((response) => {
return response.json();
})
.then((data) => {
console.log("DATA", data.list);
this.setState({ getdata: data.list });
})
.catch((err) => {
console.log(err);
});
};
render() {
const translate = this.state.getdata.map((item) => (
<Translate
word={item.word}
definition={item.definition}
key={item.defid}
/>
));
return (
<div>
<div>
<form>
<input
type="text"
name="term"
value={this.state.term}
placeholder="Enter a word here"
onChange={this.handleChange}
></input>
<button onClick={this.submit}>Search</button>
</form>
{translate}
</div>
</div>
);
}
}
export default Form;
Translate.js
import React from "react";
export default function Translate(props) {
const { word, definition } = props;
return (
<div>
<div>
<div>{word}</div>
<div>{definition}</div>
</div>
</div>
);
}

Related

How can I pass an object ID from mapped array to backend?

I want to pass the ID of an object to the backend. The objects are mapped from the array and there should be a separate button for each one so that the ID of each individual object can be pass to the backend.
The communication between backend and frontend works. The only problem is that the ID is not sent to the backend when the submit button is clicked. If I would now work with an OnChange and enter the ID myself in the text field, then it would work without any problems.
Does somebody has any idea?
Here my code:
import React from 'react';
import {format} from "date-fns-tz";
import {Link} from "react-router-dom";
import MailQueueDataService from "../services/mail_queue.service";
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {
mailqueues_unsent: {},
loading: false
}
this.parentClassFunction = this.parentClassFunction.bind(this);
}
parentClassFunction = () => {
console.log("TEST");
event.preventDefault();
const url = "/api/v1/mail_queues/authorize_mail_queue";
const { id } = this.state;
const body = {
id,
};
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "POST",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json"
},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then(response => this.props.history.push(window.close()))
.catch(error => console.log(error.message));
}
render() {
return (
<div>
<Child
parentClassFunction={this.parentClassFunction}
/>
</div>
)
}
}
class Child extends React.Component{
constructor(props){
super(props);
this.state = {
mail_queues_unsent: [],
loading: false
}
}
onClickSubmitButton = () =>{
this.props.parentClassFunction()
};
retrieveMailQueues() {
MailQueueDataService.getAll().then(response => {
if (this._isMounted)
this.setState({
mail_queues_unsent: response.data.mailqueues_unsent,
loading: false}
)
}).catch(e => {
console.log(e)
})
}
componentDidMount() {
this._isMounted = true;
this.setState({loading: true})
this.retrieveMailQueues();
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
if (this.state.loading) {
return <div className="col text-center"> Lade Unautorisierte Mails... </div>;
} else {
const {mail_queues_unsent} = this.state;
const allMailsUnsent = mail_queues_unsent.map((mailqueues_unsent, index) => (
<div className="col">
<div key={index}>
<h4><b>Empfänger:</b>{mailqueues_unsent.company_name}</h4>
<b>Datum Versandfreigabe:</b>
{format(new Date(mailqueues_unsent.created_at), 'dd.MM.yyyy hh:mm')}
<p><b>Anzahl der Tests:</b> {mailqueues_unsent.trials_count}</p>
<b>Tests:</b>
<p>{mailqueues_unsent.trials.map(trial => <Link to={"/trials/" + trial.id}>
<p>{trial.certificate_number}</p></Link>)}</p>
<form onSubmit={this.parentClassFunction}>
<label htmlFor="id"></label>
<input
type="text"
name="id"
id="id"
value={mailqueues_unsent.id}
className="form-control"
onChange={this.onChange}
/>
<button onClick={this.onClickSubmitButton.bind(this)}>CLICK</button>
</form>
</div>
</div>
));
const noMailQueues = (
<div>
<h4>
Kein Unautorisierte Mails vorhanden.
</h4>
</div>
);
return (
<div>
{mail_queues_unsent.length > 0 ? allMailsUnsent : noMailQueues}
</div>
)
}
}
}
export default Parent;
Since you are calling a function that is passed as prop from the parent, inside the child component you should call it on submit like this (its not this but this.props):
onSubmit={this.props.parentClassFunction}

React class component state value not updating

I am new to react js. I am learning it by creating a simple app. I tried to create a simple weather app using react class component. All working fine but the result stored in a state variable is not printing in the template. I can see the API response in the console and then store the result on the 'currWeatherRes' state variable which is not showing in the template (Location is always blank)
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(){
super();
this.state = {
cityName: "",
currWeatherRes: {}
}
}
handleSubmit = (event) => {
event.preventDefault();
alert(`The name you entered was:`+ this.state.cityName);
fetch(`https://api.openweathermap.org/data/2.5/weather?q=`+this.state.cityName+`&appid=f3ee66722740d00cc6f197cbcab3d534`, {
method: 'GET'
}).then((response) => {
console.log(response)
this.setState({
currWeatherRes: response
})
//return response.json();
});
}
handleChange = (event) => {
this.setState({cityName:event.target.value});
}
render() {
return (
<div className="weather-app">
<form onSubmit={this.handleSubmit}>
<input type="text" value={this.state.cityName} onChange={this.handleChange} placeholder="Enter City"/>
<button type="submit" value="Submit">Submit</button>
</form>
{(typeof this.state.currWeatherRes.main != "undefined") ? (
<div className="weather-details">
<div className="weather-location">
<div className="location">Loctaion: {this.state.currWeatherRes.name}</div>
</div>
</div>
):('')}
</div>
);
}
}
export default App;
The problem was not related to react but the way you handled API call.
Fix:
fetch(`https://api.openweathermap.org/data/2.5/weather?q=`+this.state.cityName+`&appid=f3ee66722740d00cc6f197cbcab3d534`, {
method: 'GET'
}).then((response) => {
return response.json();
}).then((res) => {
this.setState({
currWeatherRes: res
})
});
Working code:
import React, { Component } from 'react';
class App extends Component {
constructor(){
super();
this.state = {
cityName: "",
currWeatherRes: {}
}
}
handleSubmit = (event) => {
event.preventDefault();
alert(`The name you entered was:`+ this.state.cityName);
fetch(`https://api.openweathermap.org/data/2.5/weather?q=`+this.state.cityName+`&appid=f3ee66722740d00cc6f197cbcab3d534`, {
method: 'GET'
}).then((response) => {
return response.json();
}).then((res) => {
this.setState({
currWeatherRes: res
})
});
}
handleChange = (event) => {
this.setState({cityName:event.target.value});
}
render() {
console.log(this.state.currWeatherRes)
return (
<div className="weather-app">
<form onSubmit={this.handleSubmit}>
<input type="text" value={this.state.cityName} onChange={this.handleChange} placeholder="Enter City"/>
<button type="submit" value="Submit">Submit</button>
</form>
{(typeof this.state.currWeatherRes.main != "undefined") ? (
<div className="weather-details">
<div className="weather-location">
<div className="location">Loctaion: {this.state.currWeatherRes.name}</div>
</div>
</div>
):('')}
</div>
);
}
}
export default App;

Why redux diff says that states are equal even though ther are not

For fun, I decided to write a booking app.
However ran into a problem when I get free rooms and send room data to TabComponent.js for the first time, everything works. But if I try to send the room data to TabComponent.js again, component does not update, but in redux devtools the state has changed. How to solve this problem? For more understanding, see the pictures below.
Component.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from "prop-types"
import { reservationCheck } from '../../../actions/axiosApi'
import { sendReservationProp } from '../../../actions/propActions'
class Form extends Component {
static propTypes = {
free_rooms: PropTypes.array.isRequired,
}
constructor(props) {
super(props)
this.state = {
arrival_date: '',
leaving_date: ''
}
}
handleChange = event => this.setState({ [event.target.name]: event.target.value });
handleSubmit = event => {
event.preventDefault()
this.props.reservationCheck(this.state)
}
sendFreeRoomPropToBookingTab = free_room => {
const reservation_prop = Object.assign(this.state, free_room)
this.props.sendReservationProp(reservation_prop) <--- sending room prop to tabComponent.js
}
render() {
const { arrival_date, leaving_date } = this.state
return (
<div className="booking-form-container">
<form onSubmit={this.handleSubmit}>
<input type="date" name="arrival_date" required onChange={this.handleChange} value={arrival_date} />
<input type="date" name="leaving_date" required onChange={this.handleChange} value={leaving_date} />
<button value="" type="submit">Find</button>
</form>
<div className="reservation-data-result">
{this.props.free_rooms.map(free_room => (
<div className="reservation-data-result__block" key={free_room.id}>
<img src={free_room.main_image} alt="" />
<div className="thumbnail-images">
{free_room.room_image.map(thumbnailImage => {
const [id, src] = thumbnailImage.split(': ')
return (
<div className="thumbnail-image">
<img src={src} key={parseInt(id, 10)}></img>
</div>
)
})}
</div>
<h3>{free_room.name}</h3>
<h5>price: {free_room.price}$</h5>
<a className="booking-btn">
<div className="btn-circle">
<div className="btn-arrow"></div>
</div>
<span className="btn-text" onClick={() => this.sendFreeRoomPropToBookingTab(free_room)}>Book room</span>
</a>
</div>
))}
</div>
</div>
)
}
}
const mapStateToProps = (state) => ({
free_rooms: state.roomReducer.free_rooms
})
export default connect(mapStateToProps, { reservationCheck, sendReservationProp })(Form)
action.js
import { RESERVATION_PROP } from './types'
export const sendReservationProp = reservation_prop => dispatch => {
dispatch({
type: RESERVATION_PROP,
payload: reservation_prop
})
}
reducer.js
import { GET_ROOM_DATA, RESERVATION_CHECK, RESERVATION_PROP } from '../actions/types'
const initialState = {
roomData: [],
free_rooms: [],
reservation_prop: {},
}
export default function (state = initialState, action) {
switch (action.type) {
case GET_ROOM_DATA:
return {
...state,
roomData: action.payload
}
case RESERVATION_CHECK:
return {
...state,
free_rooms: action.payload
}
case RESERVATION_PROP:
return {
...state,
reservation_prop: action.payload
}
default: {
return state
}
}
}
TabComponent.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
class BookingTab extends Component {
constructor(props) {
super(props)
this.state = {
room: this.props.reservation_prop.room,
price: this.props.reservation_prop.price,
arrival_date: this.props.reservation_prop.arrival_date,
leaving_date: this.props.reservation_prop.leaving_date,
name: '',
phone_number: ''
}
}
handleSubmit = () => {
console.log("SUBMIT!")
}
render() {
return (
<div className="booking-tab">
<div className="booking-tab-container">
<h2>Booking</h2>
<form onSubmit={this.handleSubmit}>
<h3>Room: {this.props.reservation_prop.name}</h3>
<h5>Price: {this.props.reservation_prop.price}$</h5>
<span>Arrival date: {this.props.reservation_prop.arrival_date}</span>
<span>Leaving date: {this.props.reservation_prop.leaving_date}</span>
<div className="name-input">
<input type="text" name="name" placeholder="Name" />
</div>
<div className="phone-number-input">
<input type="text" name="phone_number" placeholder="X (XXX) XXX-XX-XX" />
</div>
<button>Submit</button>
</form>
</div>
</div>
)
}
}
const mapStateToProps = state => ({
reservation_prop: state.roomReducer.reservation_prop
})
export default connect(mapStateToProps)(BookingTab)
This line const reservation_prop = Object.assign(this.state, free_room) actually modifies this.state and then sets reservation_prop to this.state.
So as long as this.state is not replaced by a completely new state, you will dispatch the same object multiple times and just modify it - which is something redux cannot detect, as stateBefore === stateAfter will hold true.
You probably want to do
const reservation_prop = Object.assign({}, this.state, free_room)
which creates a new object every time.

Changing parent state after updating childs prop component in React?

I'm newish to react. I have a fetch call in my App Component that I assign to a state. I pass that state as a prop along with a function to make a post to a child component. In my child component you can post/delete to alter the props, currently don't have a push() to add the new contact/prop. Is there a way to alter the parent component's state after I change the childs props? is there a better way to do this?
I'm trying to get the post action to update the state on the App.
App code
class App extends Component {
constructor() {
super();
this.state= {
contacts:[],
addModalShow: false,
modalIsOpen: false
}
}
componentDidMount() {
var request = new Request('http://localhost:3000/', {
method: "GET",
});
fetch(request)
.then((res) => {
res.json()
.then((data) => {
this.setState({
contacts: data.rows
})
})
})
}
toggleModal() {
this.setState({
modalIsOpen: ! this.state.modalIsOpen
})
}
addContact(event) {
this.toggleModal()
event.preventDefault();
let contactData = {
first: this.refs.first.value,
last: this.refs.last.value,
phone: this.refs.phone.value,
email: this.refs.email.value,
};
var request = new Request('http://localhost:3000/add', {
method: "POST",
headers: new Headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify(contactData)
});
console.log(this.state)
fetch(request)
.then((res) => {
res.json()
.then((data) => {
})
})
.catch((err) => {
console.log(err)
})
}
render() {
return (
<Container>
{console.log(this.state)}
<AddContact addContact={this.addContact} contacts={this.state.contacts} />
<ContactList contacts={this.state.contacts} />
<Contacts contacts={this.state.contacts}/>
</Container>
);
}
}
export default App;
Child component
class AddContact extends Component {
constructor(props) {
super(props);
this.state = {
contacts: [],
modalIsOpen: false,
}
}
toggleModal() {
this.setState({
modalIsOpen: ! this.state.modalIsOpen
})
}
render() {
return(
<Container>
<div className='header'>
<h1>
My Contacts
<button className='addContactButton' onClick={this.toggleModal.bind(this)}>+</button>
</h1>
<hr />
</div>
<Modal isOpen={this.state.modalIsOpen}>
<form ref='addContact' >
<div className='addContactHeader'>
<button className='saveButton' onClick={this.props.addContact.bind(this)}>Save</button>
<button className='cancelButton' onClick={this.toggleModal.bind(this)}>Cancel</button>
</div>
<div id="circle">
Add Photo
</div>
<div className="inputFields">
<div className='nameInputs'>
<input type='text' ref='first' placeholder='first name' />
<input type='text' ref='last' placeholder='last name' />
</div>
<div className='extraInputs' >
<input type='text' ref='phone' placeholder='phone' />
<input type='text' ref='email' placeholder='email' />
</div>
</div>
</form>
</Modal>
</Container>
)
}
}
Thanks for your time
You could use a callback function in order to update the state on the parent component (Another approach would be to use Redux updating the value in the Store, that way both components could have access to the value), here's how you could use the callback (With a little bit of ES6 refactor):
App:
class App extends Component {
state= {
contacts:[],
addModalShow: false,
modalIsOpen: false
}
componentDidMount() {
let request = new Request('http://localhost:3000/', {
method: "GET",
});
fetch(request)
.then((res) => {
res.json()
.then((data) => { this.setState({ contacts: data.rows }) })
})
}
toggleModal = () => {
this.setState({ modalIsOpen: ! this.state.modalIsOpen })
};
addContact = event => {
this.toggleModal()
event.preventDefault();
let contactData = {
first: this.refs.first.value,
last: this.refs.last.value,
phone: this.refs.phone.value,
email: this.refs.email.value,
};
let request = new Request('http://localhost:3000/add', {
method: "POST",
headers: new Headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify(contactData)
});
fetch(request)
.then((res) => {
res.json()
.then((data) => {
})
})
.catch((err) => {
console.log(err)
})
};
changeContacts = (newData) => {
this.setState({ contacts: newData });
};
render() {
const { contacts } = this.state;
return (
<Container>
<AddContact
addContact={this.addContact}
contacts={contacts}
onChildAction={this.changeContacts}
/>
<ContactList contacts={contacts} />
<Contacts contacts={contacts}/>
</Container>
);
}
}
export default App;
AddContacts:
class AddContact extends Component {
state = {
contacts: [],
modalIsOpen: false,
}
toggleModal = () => {
this.setState({ modalIsOpen: ! this.state.modalIsOpen })
};
// Here is where you'll send the info for the change of the prop
changeProp = e => {
const { onChildAction } = this.props;
onChildAction('Your new state/prop value here')
addContact(e);
};
render() {
const { changeProp } = this.props;
const { modalIsOpen } = this.state;
return(
<Container>
<div className='header'>
<h1>My Contacts
<button className='addContactButton' onClick={this.toggleModal}>+</button>
</h1>
<hr />
</div>
<Modal isOpen={modalIsOpen}>
<form ref='addContact' >
<div className='addContactHeader'>
<button className='saveButton' onClick={changeProp}>Save</button>
<button className='cancelButton' onClick={this.toggleModal}>Cancel</button>
</div>
<div id="circle">Add Photo</div>
<div className="inputFields">
<div className='nameInputs'>
<input type='text' ref='first' placeholder='first name' />
<input type='text' ref='last' placeholder='last name' />
</div>
<div className='extraInputs' >
<input type='text' ref='phone' placeholder='phone' />
<input type='text' ref='email' placeholder='email' />
</div>
</div>
</form>
</Modal>
</Container>
)
}
}
The last thing you need to do is decide where you want the change of the state/prop to be fire. Hope this helps.
to handle the parent from child you need to bind this to the child
Parent Component
class Component extends React.Component {
constructor(props) {
super(props)
this.state= {
contacts:[],
addModalShow: false,
modalIsOpen: false
}
this.addContact = this.addContact.bind(this);
}
render() {
...
return <AddContact addContact = {this.addContact} />
}
addContact(event) {
...
alert('one contact added');
...}
}
inside AddContact Component :
you can call this.props.addContact() to excute the parent function

i cant transfer data from react child to parent ang during click on child set value of input in parent

it is my first React App
i want create simple typeahead(autocomplete)
i want when i click on searched list of item, this item will show in value of my Parent input
now my click doesnt work, working only search by name
it is my parent
`
import React, { Component } from 'react';
import logo from './logo.svg';
import './Search.css';
import Sugg from './Sugg';
class Search extends Component {
constructor(props) {
super(props);
this.onSearch = this.onSearch.bind(this);
this.handleClickedItem = this.handleClickedItem.bind(this);
this.onClick = this.onClick.bind(this);
this.state = {
companies: [],
searchedList: [],
value: ''
}
}
componentDidMount() {
this.fetchApi();
console.log(this.state.companies);
}
fetchApi = ()=> {
const url = 'https://autocomplete.clearbit.com/v1/companies/suggest?query={companyName}';
fetch(url)
.then( (response) => {
let myData = response.json()
return myData;
})
.then((value) => {
let companies = value.map((company, i) => {
this.setState({
companies: [...this.state.companies, company]
})
})
console.log(this.state.companies);
});
}
onSearch(arr){
// this.setState({companies: arr});
};
handleInputChange = () => {
console.log(this.search.value);
let searched = [];
this.state.companies.map((company, i) => {
console.log(company.name);
console.log(company.domain);
const tempName = company.name.toLowerCase();
const tempDomain = company.domain.toLowerCase();
if(tempName.includes(this.search.value.toLowerCase()) || tempDomain.includes(this.search.value.toLowerCase())) {
searched.push(company);
}
})
console.log(searched);
this.setState({
searchedList: searched
})
if(this.search.value == '') {
this.setState({
searchedList: []
})
}
}
handleClickedItem(data) {
console.log(data);
}
onClick = e => {
console.log(e.target.value)
this.setState({ value: e.target.value});
};
render() {
return (
<div className="Search">
<header className="Search-header">
<img src={logo} className="Search-logo" alt="logo" />
<h1 className="Search-title">Welcome to React</h1>
</header>
<form>
<input
placeholder="Search for..."
ref={input => this.search = input}
onChange={this.handleInputChange}
/>
<Sugg searchedList={this.state.searchedList} onClick={this.onClick.bind(this)} />
</form>
</div>
);
}
}
export default Search;
`
and here my child component
i dont know how call correctly click event
import React from 'react';
const Sugg = (props) => {
console.log(props);
const options = props.searchedList.map((company, i) => (
<div key={i} >
<p onClick={() => this.props.onClick(this.props)}>{company.name}</p>
</div>
))
console.log(options);
return <div >{options}</div>
}
export default Sugg;
please help me who knows how it works
thanks a lot
In the parent you could modify your code:
onClick = company => {
console.log('company', company);
this.setState({ value: company.name});
};
and you don't need to bind this because onClick is an arrow function
<Sugg searchedList={this.state.searchedList} onClick={this.onClick} />
and in the child component, you need to use props from the parameters, not from the this context:
<p onClick={() =>props.onClick(company)}>{company.name}</p>

Categories

Resources