I want to achieve a carousel like Materialize.
Have an API from where I am fetching the data, so according to Materialize
I compared the console or Materialize default and my rendered components.
I guess the problem is, it's not inheriting the properties of carousel-item
Class carousel-item is supposed to Render inside of Class carousel.
<div className="carousel">
// These are supposed to be dynamic, below component is not present here
<div className="carousel-item">
</div>
</div>
How I am trying to render the data is in this manner.
renderAlbums(){
return this.state.albums.map(album =>
<Card song={album.name} singer={album.artist_name} src={album.cover_photo_url}/>
);
}
Rendered the data <Card />(It contains the class of carousel-item), which is supposed to place Card containing class of carousel-item.
class Carousel extends Component {
state = { albums: [] };
componentWillMount() {
axios.get('https://cors-anywhere.herokuapp.com/https://stg-resque.hakuapp.com/albums.json')
.then(response => this.setState({albums: response.data}));
}
renderAlbums(){
return this.state.albums.map(album =>
<div className="carousel-item"><Card key={album.name} song={album.name} singer={album.artist_name} src={album.cover_photo_url}/></div>
);
}
render() {
return (
<div className="carousel center">
{this.renderAlbums()}
</div>
);
}
}
export default Carousel;
This is my Card component
class Card extends Component {
render() {
return (
<div className="card z-depth-4">
<div>
<img src={this.props.src} />
</div>
<p>{this.props.song}</p>
<div className="singer">{this.props.singer}</div>
</div>
);
}
}
export default Card;
EDIT:
Want that content to display like this.
But it's not working the way it's expected.
Please suggest me, what am I doing wrong?
In axios.get, I see that you are using proxy link.
One reason is, it can be creating problems.
Other reason can be you are trying to put carousel-item into carousel.
Try adding center class to both i.e. carousel as well as carousel-item.
Check if these works.
First of all, there is nothing in your Carousel that says which element is active. You need to have a state variable that points to the active element.
Then you only need to draw [-2, -1, 0, 1, 2] offsets vs the active one. And each rendered card needs to know which offset to know their style.
Related
I am experiencing an issue where the overflow properties of Tailwind are not working with react lists. I am wondering if this is just a simple mistake on my part or if there is a work around that I need to do.
Image to It Not Working
import CoinSummary from './CoinSummary'
const Holdings = ({ coins }) => {
return (
<div className='overflow-auto p-4'>
<h2 className='text-2xl text-center font-bold mt-4'>Holdings</h2>
{coins &&
coins.map((coin, index) => {
return <CoinSummary key={index} coin={coin} />
})}
</div>
)
}
export default Holdings
I want the list of coins to stay inside of the Holdings component and if it overflows, to have a scroll bar instead. However, as you can see in the photo, it doesn't seem to be working like I expected it to.
I was able to figure it out on my own. It was because I did not specify the height to be h-full
I'm building a website with React and for the "news" section i have a list of 3 components representing the different news. They belong to a flexbox and I'm trying to make them responsive. For mobile devices i would want only one of the 3 components to be shown with the ability of clicking 2 arrows to go through the news. Like a normal image carousel, but made of components. How can I achieve this? These are the components
The code where i put all the "news"
render() {
let content = <div>Loading...</div>;
if (!this.state.isLoading) {
content = (
<Aux>
<New
image={img1}
title={this.state.news[0].title}
text={this.state.news[0].text}
date={this.state.news[0].date}
classes="new-1"
/>
<New
image={img2}
title={this.state.news[1].title}
text={this.state.news[1].text}
date={this.state.news[1].date}
classes="new-2"
/>
<New
image={img3}
title={this.state.news[2].title}
text={this.state.news[2].text}
date={this.state.news[2].date}
/>
</Aux>
);
}
return content;
}
This is the "new" component
const New = props => {
const imageStyle = {
backgroundImage: `url(${props.image})`
};
return (
<div className={`new-wrapper ${props.classes}`}>
<div className="new-image" style={imageStyle}></div>
<div className="new-content">
<h4>{props.title}</h4>
<div className="text-wrapper">
<p>{props.text}</p>
</div>
<div className="date">
<span>{props.date}</span>
</div>
</div>
</div>
);
};
To achieve your desired result I would use a carousel plugin like https://react-slick.neostack.com/
You could set it to show three slides on desktop and just one on mobile so then you would get the arrows to go through the news cards.
I would also loop every element of the array by using the map function to render all the news. That way it would dynamically create a news card for every element on your state or array. See this example How to render an array of objects in React?
Hope this helps!
I am using the event object to try and create three images next to each other. I am running into an issue where because they are returned in order, they keep stacking vertically when I want them to be in two rows, with three items per row.
Here is my current code for App.js:
function App() {
let imgGen = [{img:""},{img:""},{img:""},{img:""},{img:""},{img:""}];
let images = imgGen.map((image1) => {
return <GenSlide data={image1}/>
});
return (
<div className="App">
<Entry />
{images}
</div>
);
}
Here is my code for the GenSlide class:
function GenSlide (props) {
return (
<div class="imagePackage">
<img alt="this image is busted" width="300px" src={props.data.image}/>
<button id="theButton">Save</button>
</div>
)
}
You should use the flexbox or grid layout to accomplish this.
By default a div is a block element which puts line breaks before and after each element. If you set them to inline-block there will still be spacing in between them.
For more info read https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model
My particular use case of React is thus:
I wish to add a small React Component to a card that is an existing, fully-functional HTML element, per all the cards on the page. This React Component shall serve to implement a new feature on those cards : reverting changes.
The HTML (well, the MVCE version of it)
is something like this:
<div id="some-id" class="card float-sm-left menu-visual-card " onclick="(function(event) { console.log('I got clicked, and a modal will spawn' ) })(event)">
<div class=card-block>
<h5 class="card-title format-text">Some title</h5>
<!-- some business elements here -->
</div>
<!-- card footer -->
<div class=customized-indicator-react></div>
</div>
The React Component
in its tl;dr version is the following:
class CustomizedIndicatorComponent extends React.Component {
constructor(props) {
super(props)
// business logic
let active = this.props.active
this.state = {
active : active
}
}
toggleActive = () => {
this.setState({
...this.state,
active : !this.state.active
})
}
// setup
componentDidMount() {
// here's where I tried to add a jQuery onclick listener to stop propagation, only to have the React Component listener get stopped
}
// teardown
componentWillUnmount() {
console.log("CustomizedIndicatorComponent destroyed!")
}
// the UI logic
render() {
if (this.state.active) {
return (
<div>
<div
className="badge badge-sm badge-info float-sm-left customized"
style={{marginRight:"10px"}}
>Customized</div>
<div
onClick={(e) => {
e.stopPropagation()
this.toggleActive()
}}
title="Click to undo customizations">
<i className="fa fa-undo" aria-hidden="true"></i>
</div>
</div>
)
}
return <div />
}
}
What happens when you run this?
When I run this, it renders. However, when I click the widget to "de-activate" the element, the container's event-handler still fires!!
I know there is a slew of internet questions about this issue or something close to it, but none of the ones I could find seem to be about this exact use case.
Also, adding an event listener in componentDidMount doesn't work, as that prevents anything from firing!
Is there any way I can make this work without wasting developer-hours refactoring everything including the parent HTMLElements?
A "hacky" way you may consider is to get the parent's id from inside the React component and disable the click event from there.
If id could not be passed as a property to the React component, you can try using ReactDOM.findDOMNode(this).parentNode.getAttribute("id") to get it and then disable the event using:
document.getElementById(id).style.pointerEvents = 'none';
I'm new to react and have to make a project for my bootcamp with it and I am having trouble getting every movie component I render to have an individual button. Every time I click one button, the rest of the buttons on the page act like they are also clicked. Here is my movie component that is being called on.
Heres my first row of components and the buttons are the green ones on the bottom left corner. https://files.slack.com/files-pri/T571CRHGE-F826BKX7S/api.png.
importReact, { Component} from"react";
importAPIfrom"../utils/API"
classMovieextendsComponent{
constructor(){
super();
this.state={
color:'green',
icon:'add',
result:[]
};
}
componentDidMount() {
this.topMovies();
}
topMovies=() =>{
API.topMovies()
.then(res=>this.setState({ result:res.data.results}))
.catch(err=>console.log(err));
}
handleClick=event=>{
if(this.state.color==='green'){
this.setState({color:'red'});
} else{
this.setState({color:'green'});
}
if(this.state.icon==='add') {
this.setState({icon:'remove'});
} else{
this.setState({icon:'add'});
}
}
render() {
constimgURL="https://image.tmdb.org/t/p/w300/"
return(
<div>
{
this.state.result.map((movieList) =>(
<div className="col s4 movieBox">
<div className="card">
<div className="card-image">
<img src={imgURL +movieList.poster_path} />
<span className="card-title"><a id={this.state.color} onClick={this.handleClick} className="btn-floating btn waves-effect waves-light"><i className="material-icons">{this.state.icon}</i></a></span>
</div>
<div className="card-content movieInfo">
<p>Title:{movieList.title}</p>
<p>Genre:{movieList.genre_ids}</p>
<p>Rating:{movieList.vote_average}</p>
</div>
</div>
</div>
))
}
</div>
)
}
}
exportdefaultMovie;
You need to bind the handleClick function ( in fact all functions ) inside the constructor:
constructor(){
super();
this.state={
color:'green',
icon:'add',
result:[]
};
this.handleClick = this.handleClick.bind(this);
}
onClick={()=> this.handleClick()} will also work.
.map() calls a provided callback for each element in your array. So this means that you are creating several buttons that will execute the same event on each of your elements. I suggest creating a row component that handles your onClickEvent and then you could pass the component an id or use an in line arrow function () => this.handleClick(). (this does create a anonymous function on each click and could potentially be bad for performance in larger apps but could work in your case if you don't want to create a row component)
Also you should read up on why using keys with unique ids is important.
https://coderwall.com/p/jdybeq/the-importance-of-component-keys-in-react-js
Hope that helps.