How to get array in class component to another file in react? - reactjs

The real situation is that I want to get the value of radio button in one file and let them show in another file, therefore I can let user know what they select before.
The code that use select the radio button:
class Usurvey extends Component {
constructor(props){
super(props);
this.state = {
uid: uuid.v1(),
studentName: '',
answers: {
answer1: '',
answer2: '',
answer3: ''
},
isSubmitted: false
};
this.nameSubmit = this.nameSubmit.bind(this);
this.answerSelected = this.answerSelected.bind(this);
this.questionSubmit = this.questionSubmit.bind(this);
}
render(){
<form onSubmit={this.questionSubmit}>
<div className="card">
<div className="video">
<ReactPlayer url={Array[0].url} />
</div>
<label>Do you think the video is fake or real? </label> <br />
<input type="radio" name="answer1" value="real" onChange={this.answerSelected} />Real
<input type="radio" name="answer1" value="fake" onChange={this.answerSelected} />Fake
</div>
<div className="card">
<div className="video">
<ReactPlayer url={Array[0].url} />
</div>
<label>Do you think the video is fake or real? </label> <br />
<input type="radio" name="answer2" value="real" onChange={this.answerSelected} />Real
<input type="radio" name="answer2" value="fake" onChange={this.answerSelected} />Fake
</div>
return(
<div>
{studentName}
{questions}
</div>
);
}
}
export default Usurvey;
The code file I want to input the value of radio button.
'use strict'
import React, { useState } from 'react';
import ReactPlayer from 'react-player';
import Array from '../Array';
import Usurvey from '../Usurvey2';
export default () => {
return (
<div>
<div className="video">
<ReactPlayer url={Array[0].url} playing/>
<div>
<p>Your guess: </p>
<p>{Usurvey.props.Answer[0]}</p>
<p>Right Answer:</p>
<p>{Array[0].name}</p>
</div>
</div>
</div>
)
}
Now I tried to import the Usurvey from the last file and use prop to get answer, but it does not work

Props are not static or hardcoded data that can be accessed by just import the file. Moreover, this is not a way to pass props from a parent component to a child component.
Either you need to lift up the state in Usurvey component to its parent component from where you can pass it to the component where you want the radio button's value.
Or you can pass onSubmit from handler as a prop to Usurvey component from its parent component. The parent component will store the form data and pass it to the required component.
Or if both the component are at a different level of hierarchy then you can also use redux instead of passing it to each component in the path.
You can read more about components and props over here.
Edit
class ParentComponent extends Component {
state = {
submittedQuestion: {} // depending on your logic you can store all the
questions or just one.
}
onQuestionSubmit = () => {
// store data in state.
}
render (){
const {submittedQuestion} = this.state;
return (
<Usurvey onQuestionSubmit={this.onQuestionSubmit} />
<QuestionSubmittedView submittedQuestion={submittedQuestion}/>
);
}
}

Related

How to access state/props in another jsx file

This is a whitebox.jsx file where i have a state "wbimage", it should contain an image url that will be displayed in className="wbimgframe". I want to access and edit this state i.e, give image url to "wbimage" in another jsx file - javaa.jsx
whitebox.jsx
import "./whitebox.css"
class Whitebox extends Component {
constructor(props) {
super(props);
this.state ={
wbimage: '',
};
}
render() {
return (
<div>
<div className="wbdemo" >
<div className="wbimgframe">
<center>
<img src={this.state.wbimage} alt="Given image will be displayed here"/>
</center>
</div>
<div className="wbdemobookname">
<label>Book Name</label>
</div>
<div className="wbdemobookauthor">
<i><label>By </label>
<label>Book Author</label></i>
</div>
</div>
</div>);
}
}
export default Whitebox;
I have tried this, but still nothing is displayed in image.
javaa.jsx
import Whitebox from "./whitebox";
import "./javaa.css";
class Javaa extends Component {
render() {
return (
<div>
<br/><br/><br/><br/><br/>
<div className="javaamp">
<Whitebox>
{this.props.wbimage} = "https://cdn.codegym.cc/images/article/960defdc-e2f5-48ac-8810-d8b4436a88a7/512.jpeg"
</Whitebox>
</div>
</div>);
}
}
export default Javaa;
Please help, I am a beginner. So if this question seems easy, please don't mind :)
parent component (From where you have to send the data)
<Whitebox wbimage="https://cdn.codegym.cc/images/article/960defdc-e2f5-48ac-8810-d8b4436a88a7/512.jpeg">
Child component (from where you are gonna receive the data and use it in your HTML.
console.log(this.props.wbimage)
Check out this to understand better https://reactjs.org/docs/components-and-props.html

Squaring the value of an input box in React

I am new to learning React and doing a little test project each day. Today, I am trying to create an input box that when I click a Submit button, it alerts the square of a number. Nice and simple. But, I am trying to do this without using State. Just trying to understand how. Here is my code but something is missing. I think I am close!
Any ideas?
import { render } from '#testing-library/react';
import React from 'react';
class App extends React.Component {
sayHi = props => {
alert(this.props.mySentProps);
};
squareTheNumber = () => {
alert('this is the squared number'+ );
};
render() {
return (
<div>
<div onClick={this.sayHi}>
<h1>Hello World</h1>
</div>
<div>
<input type="text" placeholder={'Enter a number to square'} />
</div>
<div>
<button onClick={this.squareTheNumber}>Submit me</button>
</div>
</div>
);
}
}
export default App;
Try this:
import React from "react";
import "./styles.css";
class App extends React.Component {
sayHi = (props) => {
alert(this.props.mySentProps);
};
squareTheNumber = (event) => {
event.preventDefault();
// Should be the same as input's "name" or "id" property
// Docs: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements
const { number } = event.target.elements;
alert(`this is the squared number: ${number.value ** 2}`);
};
render() {
return (
<div>
<div onClick={this.sayHi}>
<h1>Hello World</h1>
</div>
<div>
<form onSubmit={this.squareTheNumber}>
<input
name="number"
type="text"
placeholder="Enter a number to square"
/>
<button type="submit">Submit me</button>
</form>
</div>
<div></div>
</div>
);
}
}
export default App;
P.S.: render from #testing-library/react is used for testing purposes only. See docs here. Class components have their own field with the same name.
As said, there is no clean way to do it without state or any extensions. The best way is to use state and make things clean. But another way you can do it is to use JQuery.
For example:
You can assign the <input> an id, say myId. Then you do this:
var content = $('#myId').content;
And then you can change the content in the p by assigning it a new value.
But using JQuery kinds of defeats the purpose of React, so I would recommend using state.
You can use refs to access mounted elements directly.
https://reactjs.org/docs/refs-and-the-dom.html

How to make filter by name and address in React.js

I'm new with React.js. I'm making filter by name and address but I don't know how to do this with separate components. I have main component Speakers - in this component I receive json and send this data to Filter and List. In List.js I get data and display all speaker items(all json). In Filter I want to make search by name and address. I don't know how to bind component filter and list. I'll appreciate if you help me. I know that Redux help working with data in React but I want to understand how to do this without it.
enter image description here
Speakers.js
import React, {Component} from 'react';
import Filters from './Filters';
import List from './List';
class Speakers extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
items: []
}
}
componentDidMount() {
this.setState({isLoading: true});
fetch("https://randomapi.com/api/6de6abfedb24f889e0b5f675edc50deb?fmt=raw&sole")
.then(res => res.json())
.then(
(result) => {
this.setState({
items: result,
isLoading: false
});
console.log(result);
}
)
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
return (
<div className="speakers">
<div className="container-fluid">
<Filters getItems={this.state} />
<List getItems={this.state} />
</div>
</div>
);
}
}
export default Speakers;
List.js
import React, {Component} from 'react';
class List extends Component {
render() {
const {items, isLoading} = this.props.getItems;
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="speakers__list">
<div className="row">
{items.map((item, index) => (
<div className="col-md-3" key={index}>
<div className="card form-group shadow">
<div className="card-body text-center">
<h5 className="card-title">{item.first} {item.last}</h5>
<p>{item.email}</p>
<p>{item.address}</p>
<p>{item.balance}</p>
<p>{item.created}</p>
</div>
</div>
</div>
))}
</div>
</div>
)
}
}
export default List;
Filters.js
import React, {Component} from 'react';
class Filters extends Component {
render() {
return (
<div className="filters">
<div className="alert shadow">
<form>
<div className="container-fluid">
<div className="row">
<div className="col-md-5">
<label>Name/Surname</label>
<input type="text" className="form-control" />
</div>
<div className="col-md-5">
<label>Address</label>
<input type="text" className="form-control"/>
</div>
<div className="col-md-2 align-self-center text-center">
<button className="btn btn-primary">Search</button>
</div>
</div>
</div>
</form>
</div>
</div>
);
}
}
export default Filters;
One way to move forward (possibly the best way, IMO) is this:
Come up with a data model to describe a single "filter". This could be as simple as an object that describes a name string and an address string that items need to be filtered using. The design of this is up to you; pick whatever works out best.
Then, build two sets of behavior into Speakers:
The ability to receive filtration instructions from Filters. You can achieve this by writing a function in Speakers that acts as a callback function when something changes in Filters. Pass this function as a prop to Filters and have Filters call it when its state changes (meaning, when you get user interaction).
The ability to send this filter object to List. Every time the callback function is called, have Speakers send it down to List. You can achieve this by storing what Filters sends back in Speakers' state and passing that state item down to List as a prop. That should update List's props every time Filters calls the callback function and thus affects Speakers' state.
Then, build behavior in List such that it changes its rendering behavior based on this filter object. Make sure to detect props updates so that it works on the fly.

Material Components Web and React: Cannot read property 'querySelector' of undefined;

I am trying to build a Modal component taking advantage of React and Material Components Web. The visibility of Modal is inherited from the parent state as props:
import React, {Component} from 'react';
import {MDCFormField} from '#material/form-field/';
import {MDCTextfield} from '#material/textfield/';
import './modal.scss';
export default class Modal extends Component {
componentDidMount() {
this.email = new MDCTextfield(this.email);
this.pwd = new MDCTextfield(this.pwd);
}
componentWillUnmount() {
this.email.destroy();
this.pwd.destroy();
}
render() {
if (this.props.isModalOpen){
return (
<div id="modal-container">
<div id="mask"></div>
<div id="modal">
<form className="mdc-form-field">
<div ref={(div) => {this.email = div}} className="mdc-textfield">
<label type="email" htmlFor="email" className="mdc-textfield__label">Your email</label>
<input type="text" id="email" className="mdc-textfield__input"/>
<div className="mdc-textfield__bottom-line"></div>
</div>
<div ref={(div) => {this.pwd = div}} className="mdc-textfield">
<label htmlFor="pw" className="mdc-textfield__label">Password</label>
<input type="password" id="pw" className="mdc-textfield__input" required minLength={8}/>
<div className="mdc-textfield__bottom-line"></div>
</div>
</form>
</div>
</div>
);
} else {
return null
}
}
}
As soon as the app initialise an error appears "TypeError: Cannot read property 'querySelector' of undefined”
Of course it does since the since as the Modal is returning null.
so i tried to initialise Material Components as
componentDidMount() {
this.email = this.email && new MDCTextfield(this.email);
this.pwd = this.pwd && new MDCTextfield(this.pwd);
}
In this case the error is not thrown anymore but obviously the components are not initialised.
I did not come up with a pattern to solve this problem. Also a css approach did not work ( the idea was to toggle .someClass {display: none} from the main container ).
/** SOLVED **/
Ok I came up with a working pattern to solve the problem.
The problem was in the architecture of the app and the encapsulation of the components was not appropriate.
This is a parent component called Modal:
import React, {Component} from 'react';
import EmailField from './email-field';
import PwdField from './password-field';
import './modal.scss';
export default class Modal extends Component {
render() {
if (this.props.isModalOpen){
return (
<div id="modal-container">
<div id="mask"></div>
<div id="modal">
<form className="mdc-form-field">
<EmailField />
<PwdField />
</form>
</div>
</div>
);
} else {
return null
}
}
}
Than we have Children components as
import React, {Component} from 'react'
import {MDCTextfield} from '#material/textfield/';
export default class EmailField extends Component {
componentDidMount(){
this.email = new MDCTextfield(this.email);
}
componentWillUnmount(){
this.email.destroy();
}
render(){
return(
<div ref={(div) => {this.email = div}} className="mdc-textfield">
<label type="email" htmlFor="email" className="mdc-textfield__label">Your email</label>
<input type="text" id="email" className="mdc-textfield__input"/>
<div className="mdc-textfield__bottom-line"></div>
</div>
);
}
}
I was trying to init and destroy from a different scope of MDCTextfield elements.
You should try out the react version of this library.
Try to console.log(this.email). Afterwards you will see, that ref that you try to pass is not a selector, this is expected when you initialise matertial-components.
#Fawaz answer is correct, but you can instantiate it the way you want, even on div.
Showcase: https://www.webpackbin.com/bins/-KwEsyJR3O3eW50gX2pq
Did you using components like i am using there?
Use this for reference:
Material Components Textfield, Manual Instantiation

Reactjs: how to put the html template in a separate file?

I'm new to React. I'm much more familiar with Angular2+. In Angular, every component has a separate html file. However, in React, I see that render function itself includes the html template. For example,
import React, { Component } from 'react';
class HelloWorld extends Component {
render() {
return (
<h2> Hello World </h2>
);
}
}
export default HelloWorld;
Well I want to take
<h2> Hello World </h2>
outside the js file and put it in a separate html and import the html file to render function, for example
render() {
return (
import content of helloworld.html
);
}
Do you know how to do it?
In React you would typically make a child component and import it into the parent component.
Since your child component here would just be static markup i.e <h2>Hello World</h2>, you don't need to worry about component state.
Therefore, you could do the following:
make a functional (aka stateless or dumb) component for your text. You could name it HelloWorldText as an example.
import this functional component into your parent component HelloWorld.
Your functional component would look something like this:
HelloWorldText.js
const HelloWorldText = () => ( <h2> Hello World </h2> );
export default HelloWorldText;
Then you would import this functional component HelloWorldText into your parent component HelloWorld like so:
HelloWorld.js
import React, { Component } from 'react';
import HelloWorldText from './path/to/HelloWorldText';
class HelloWorld extends Component {
render() {
return (
<HelloWorldText />
);
}
}
export default HelloWorld;
Here's a CodePen Demo with this code.
Unfortunately on CodePen you can't export and import components, but hopefully it still gives you an idea on how to use a child component inside a parent component.
Note: In React you want your components to be as general as possible. You would probably end up making a Text component instead of a HelloWorldText component.
Then you would pass text dynamically into the Text component using props.
Here is a CodePen Demo of this in action.
You can move the JSX part into a separate file and import that file in your component class
Here's an example
Signin.jsx
import React from 'react';
export const SigninJsx = () => {
return (
<div className="container">
<form className="form-signin">
<h2 className="form-signin-heading"> Please sign in </h2>
<br />
<label htmlFor="inputEmail" className="sr-only"> Email address
</label>
<input type="email" id="inputEmail" onChange={this.handleEmailChange} className="form-control" placeholder="Email address" required autoFocus />
<br />
<label htmlFor="inputPassword" className="sr-only"> Password</label>
<input type="password" id="inputPassword" onChange={this.handlePasswordChange} className="form-control" placeholder="Password" required />
<br />
<button className="btn btn-lg btn-primary btn-block" onClick={this.signIn} type="button"> Sign in
</button>
</form>
</div>
)
}
Signin.js
import React, { Component } from 'react';
import {SigninJsx} from './Signin.jsx';
export class Signin extends Component {
constructor(props){
super(props);
this.handleEmailChange = this.handleEmailChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
this.state = {
email:'',
password:''
};
this.signIn = this.signIn.bind(this)
}
handleEmailChange(e){
this.setState({email:e.target.value})
console.log("Error Change");
}
handlePasswordChange(e){
this.setState({password:e.target.value})
}
signIn(){
alert('Email address is ' + this.state.email + ' Password is ' + this.state.password);
}
render() {
return (
<SigninJsx />
)
}
}
Please checkout this Medium link
This will be your React component declaration and
you need to import the template.js file inside here and render it in context of the component 'Abc' (index.jsx):
import template from './template';
export default class Abc extends React.Component {
render() {
return template.call(this)
}
}
Separate js file will have template as follows (template.js):
import styles from './styles.module.css';
const template = () => (
<div className={styles.outerContainer}>
<div className={styles.middleContainer}>
<div className={styles.innerContainer}>Hello, World</div>
</div>
</div>
);
export default template;
Additionally, we can import CSS modules inside the template and maintain them in serapate file as well, as follows (styles.module.css):
.outerContainer {
backgroundColor: red;
}
/* etc... etc... */
for now , it is not possible to load template from html file.

Resources