Materialize carousel-item not inheriting default properties - html

Able to fetch the data from API.
But the problem is when I try to map the carousel-item inside class carousel.
The properties are not being inherited.
When I inspect, I see there are carousel-item inside carousel, but they are not having the default properties.
This is my Carousel Class
class Carousel extends Component {
constructor(props){
super(props);
this.state = { albums: [] };
}
componentWillMount() {
axios.get('http://rallycoding.herokuapp.com/api/music_albums')
.then(response => this.setState({albums: response.data}));
}
renderAlbums(){
return this.state.albums.map(album =>
<Card song={album.title} singer={album.artist} src={album.thumbnail_image}/>
);
}
render() {
return (
<div className="carousel center">
{this.renderAlbums()}
</div>
);
}
}
export default Carousel;
This is my Card Component
import React, { Component } from 'react';
import '../../App.css';
class Card extends Component {
render() {
return (
<div className="carousel-item center">
<div className="card z-depth-4">
<div>
<img src={this.props.src} className="responsive-img"/>
</div>
<p>{this.props.song}</p>
<div className="singer">{this.props.singer}</div>
</div>
</div>
);
}
}
export default Card;
Please suggest if there is any other way, to import it.
Already have initialised carousel and it's working if I try the Materialize Example

Try performing your API call in componentDidMount instead of componentWillMount.
The latter is called before the initial render, and thus, if your API call returns before the component finishes mounting, the setState statement will not cause a re-render.
With the former, setting the state will always cause a re-render to occur. React documentation recommends initiating data requests from remote endpoints from componentDidMount. See here.

Related

Angular show fetched data after click dropdown button

I use angular at the frontend and .net core at the backend. I have a trivial problem and figure it with a video below. I spend hours and hours and still couldn't solve the problem.
I simply fetch data from my web api. And use *ngFor for display the data. But the problem is data is not shown before click any dropdown button.
Btw, dropdown button does not have any click event. It's simple language selector.
When I click language selector dropdown button, it expands and at the same time my data display on the screen.
I get my data ngOnInit. I check the data on debug mode and it's ok. I really spend hours and hours...still couldn't find any solution.
My html code :
<div class="container">
<div *ngFor="let d of devices"> --> I put here breakpoint and it run when I click dropdown btn
<span>{{d.name}}</span>
</div>
</div>
My .ts code:
import { ChangeDetectorRef, Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { ToastrService } from 'ngx-toastr';
import { Observable } from 'rxjs';
import { Pagination } from '../../../_helpers/Pagination';
import { deviceListModel, NewDeviceModel } from '../../admin-panel.model';
import { AdminPanelService } from '../../admin-panel.service';
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
devices : Array<deviceListModel>; ---> I also try with public deviceList : deviceListModel[]; nothing change
constructor(private service : PanelService, private router : Router) { }
ngOnInit(): void {
this.getDeviceList();
}
getDeviceList() {
this.service.getDeviceList().subscribe(res => {
this.devices = res;
})
} ---> This part works fine. Data comes true from the backend before click the dropdown button.(I checked in debug mode with breakpoints)
}
Visiulize my problem with below link;
https://media.giphy.com/media/jYGHN1Ndxyeqhtn0ZR/giphy.gif
fullscreen with low res : https://giphy.com/gifs/jYGHN1Ndxyeqhtn0ZR/fullscreen
Edit :
When I try just display one of the data like devices[0].name;
<div>
<span> {{devices[0}.name}} </span>
</div>
I get data on page but with an error in console.
The error comes three times and the error is ;
core.js:4352 ERROR TypeError: Cannot read property '0' of undefined
Try putting the this.devices = res; into the NgZone
constructor(..., private _ngZone: NgZone)
this._ngZone.run(() => { this.devices = res; });
Can you try to put an *ngIf in the container? Like so:
<div class="container" *ngIf="devices?.length">
<div *ngFor="let d of devices">
<span>{{d.name}}</span>
</div>
</div>
In this case, the template will only be rendered when the backend call has completed successfully (and has results).

Custom HTML attributes on React component

I'm trying to add a custom HTML attribute on a React component:
const Parent = () => (
<div className="parent">
<Child data-custom="foo" />
</div>
);
Where Child is another React component, but the attribute gets stripped on the output HTML. I'm aware that I could simply add the attribute on the Child root element, like so:
const Child = () => <div className="child" data-custom="foo" />
Or read the attribute in the Child component via props, but that's not what i'm looking since that would couple the attribute with the component, and I'm looking for a more contextual approach (the attribute would be used for test automation purposes).
Is there a clean way to do that in React?
I'm also considering writing a Babel plugin to add the attribute or prevent the stripping, but that would be another question.
Thanks!
React element doesn't necessarily correspond to DOM element that could have HTML attributes. React component can be rendered to multiple DOM elements or no elements at all.
If Child should be able to provide additional props or attributes to child DOM element, it should pass them explicitly:
const Child = props => <div className="child" {...props} />
This way data-custom="foo" will be passed to <div>.
For this, you can try this in your react script.
const MyCompo = () => {
return (
<div>
<p>HTML Code</p>
</div>
);
}
export default About;
Otherwise you can create class and then define your components and then export them.
import React from 'react';
import '../assets/css/style.css';
import '../assets/css/pure-min.css';
import '../assets/css/custom.css';
import 'font-awesome/css/font-awesome.min.css';
import $ from 'jquery';
class FirstScreen extends React.Component {
constructor(props) {
super(props);
this.handleLoad = this.handleLoad.bind(this);
}
componentDidMount() {
window.addEventListener('load', this.handleLoad);
}
handleLoad() {
}
render() {
return <div>HTML Code</div>;
}
}
export default FirstScreen;
You could use the below syntax
const Parent = () => (
<div className="parent">
<Child data-custom="foo"/>
</div>
);
const Child = ({...props}) => (<div className="child" {...props} />)

How to set a div containing many images as background?

This is the motive
The background image is not a single file but collection of many thumbnail captured inside a div tag
Code:
import React, { Component } from 'react';
class Background extends Component{
constructor(props){
super(props)
this.state={pictures:[]}
}
componentDidMount(){
fetch('https://randomuser.me/api?results=300')
.then(results=>{
return results.json();
}).then(data=>{
let pictures=data.results.map((pic)=>{
return(
<span key={pic.login.uuid}>
<img src={pic.picture.medium} alt=''/>
</span>
)
})
this.setState({pictures:pictures})
})
}
render(){
return(
<div className="Container1">
{this.state.pictures}
</div>
)
}
}
export default Background;
How should my css should be for Container1 class and for my app class which has the main content?
The following link would be helpful :
https://www.webucator.com/how-to/how-use-multiple-background-images-with-css.cfm
Another solution would be to create a css flex container and dynamically create a element for each image of your pictures array.
Check this link for more info on flex layout.

Modelling Dynamic Forms as React Component

How to model dynamic forms as a React Component?
For example I want to create a form shown in an image below:
How can I model this as a React component?
How can I add dynamicity to that component? For example, clicking on "+ Add" button creates another empty textbox and puts it right below the other already rendered textboxes (as shown in an image below).
Can someone help me with the code for the Form below?
In tags I see redux so I can suggest redux-form. Here you have an example of dynamic forms with redux-form.
The difference is in the fact, that beyond the state of form values, we also need to handle the state of form shape/structure.
If you render the inputs by traversing some state object, that is representing the shape of the form, than new input is just a new entry in this state object. You can easily add or remove input fields on the form by managing that state object. E.g. you can write something like this (pseudo react code):
// inputs state of math and algorithms
const state = { math: [obj1, obj2], algorithms: [obj1, obj2] } // obj ~= {id, value}
// render math inputs
const mathMarkup = state.math.map(obj => <input value={obj.value} onChange={...} />)
// add handler for math field
const addMath = () => setState(prevState => ({ math: [...prevState.math, newObj]}))
Here is the example of such form - codesandbox. It's not 100% as on your screen, but the idea should be understandable. Since there are some unclear requirements on your form, I implemented only first two sections, so you can grasp the idea. And, there are no styles :shrug:
Also, you can extract renderXyz methods to separate components, and improve state shape to meet your needs.
I can help you with a reduced way
import React , {Component} from 'react'
import { connect }from 'react-redux'
class main extends Component{
render(){
return(
<div>
<BaselineMath/>
<Algorithms />
</div>
)
}
}
const mapStateToProps = ({}) => {
return{}
}
export default connect (mapStateToProps,{})(main)
class BaselineMath extends Component{
constructor(props){
super(props);
this.state={rows:[1]}
}
_getRows{
return this.state.rows.map((res,key)=>{
return <input placeholder="etc..."/>
})
}
onClickAdd(){
let rows = this.state.rows
rows.push(1)
this.setState({
rows
})
}
render(){
return(
<div>
<Button onClick={this.onClickAdd.bind(this)}>ADD row</Button>
{this._getRows()}
</div>
)
}
}
export default (BaselineMath)
class Algorithms extends Component{
constructor(props){
super(props);
this.state={rows:[1]}
}
_getRows{
return this.state.rows.map((res,key)=>{
return <input placeholder="etc..."/>
})
}
onClickAdd(){
let rows = this.state.rows
rows.push(1)
this.setState({
rows
})
}
render(){
return(
<div>
<Button onClick={this.onClickAdd.bind(this)}>ADD row</Button>
{this._getRows()}
</div>
)
}
}
export default (Algorithms)
you can do the algorithm with anything you want

React: Create a new html element on click

I've used React for a couple of weeks now but I have this simple problem that I can't seem to wrap my head around. It's about creating new html elements.
I would just like to know in general if the way that I went about it, is the "right way" or is there another preferred way to create new html element with a click function.
For some reason this problem took awhile for me to figure out and it still feels a bit strange, that's why I'm asking.
Thanks in advance!
import React, { Component } from 'react';
import './Overview.css';
import Project from './Project';
class Overview extends Component {
constructor() {
super()
this.state = {
itemArray: []
}
}
createProject() {
const item = this.state.itemArray;
item.push(
<div>
<h2>Title</h2>
<p>text</p>
</div>
)
this.setState({itemArray: item})
//console.log(this.state)
}
render() {
return (
<div className="Overview">
<p>Overview</p>
<button onClick={this.createProject.bind(this)}>New Project</button>
<Project />
<div>
{this.state.itemArray.map((item, index) => {
return <div className="box" key={index}>{item}</div>
})}
</div>
</div>
);
}
}
export default Overview;
No, this is not a correct approach. You shouldn't be generating HTML elements like that, nor keep them in state - it is against React to manipulate DOM like that. You won't be able to utilize Virtual DOM is the first thing that I can think of.
What you should do instead is keep all data that is needed for rendering in state and then generate the HTML element from there, for instance
createProject() {
const item = this.state.itemArray;
const title = '';
const text = '';
item.push({ title, text })
this.setState({itemArray: item})
}
render() {
return (
<div className="Overview">
<p>Overview</p>
<button onClick={this.createProject.bind(this)}>New Project</button>
<Project />
<div>
{this.state.itemArray.map((item, index) => {
return (
<div className="box" key={index}>
<div>
<h2>{item.title}</h2>
<p>{item.text}</p>
</div>
</div>
)
})}
</div>
</div>
);
}