Add fade-in animation to a list element in React - reactjs

I have the following code that display a table's data from Laravel using axios in React.
The data is displayed in real time. How can I add a fade-in animation each time a new element is added ? https://socket.io/ shows exactly what I want to do in the example on the right.
Note that the element in the li tag is added from an event that is fired up from a creation controller.
The component :
import React,{Component} from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';
import Echo from "laravel-echo";
class Patient extends React.Component {
constructor(props) {
super(props)
this.state = {
patients : [],
};
}
componentDidMount() {
axios.get('api/patients')
.then(response => {this.setState({patients: response.data})})
.catch(err => console.log(err));
window.Echo.channel('home')
.listen('NewPatient', newPatientData => {
this.setState({
patients: this.state.patients.concat(newPatientData)
})
}, e => {
console.log("Error", e)
})
}
render() {
return (
<div>
<ul> { this.state.patients.slice(0).reverse().map(patient => <li>{patient.nom}</li>)} </ul>
</div>
)
}
}
export default Patient;

You can do this pretty easily with CSS animations. I've created an example below for you and if you check out the CSS, you'll see the keyframe animation which is then used by the .fadeIn selector and that class is then applied to the <li> element.
https://codesandbox.io/s/dreamy-frog-r6sr8?file=/src/styles.css

Related

How to select specific element in react.js

I want to select specific element with className "material-icons-outlined" and add new class to that element
In javascript i would do it like this
document.querySelectorAll(".material-icons-outlined").forEach(icon => {
icon.classList.add("notranslate");
})
But in react that doesn't work though, so how to do that in a react way?
You can still do that in React, just put those lines in useEffect:
useEffect(() => {
document.querySelectorAll(".material-icons-outlined").forEach((icon) => {
// check if already has the class
if (!icon.classList.contains("notranslate"))
icon.classList.add("notranslate");
});
});
Checkout ref or useRef in reactjs It is your answer.
class App extends React.Component {
componentDidMount() {
this.yourRef = React.createRef()
}
render() {
return (
<div>
<div id="divR" ref={this.yourRef}>...</div>
</div>
)
}
}

Repeating same input not showing

I'm making an application using Laravel and React.
I made an event in laravel to display data in real time and I'm using "React Transition Group" to add an animation to the added data.
The problem is, when I'm adding data normally without this package, the data is showing correctly, but once added, the animation and data are working fine except when repeating the same data.
For example if I add in {patient.nom} and {patient.prenom} values such as John & Doe. They will appear, but if I put them again, they will not, but in database they are registered perfectly.
After some tests I'm pretty sure it has to do with the key in
<CSSTransition
key={patient.nom,patient.prenom}
timeout={500}
classNames="item"><CSSTransition>
Whole component :
import React,{Component} from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';
import Echo from "laravel-echo";
import {
ListGroup,
Button,
} from 'react-bootstrap';
import {
CSSTransition,
TransitionGroup,
} from 'react-transition-group';
import './styles.css';
class Patient extends React.Component {
constructor(props) {
super(props)
this.state = {
patients : [],
};
}
componentDidMount() {
axios.get('api/patients')
.then(response => {this.setState({patients: response.data})})
.catch(err => console.log(err));
window.Echo.channel('home')
.listen('NewPatient', newPatientData => {
this.setState({
patients: this.state.patients.concat(newPatientData)
})
}, e => {
console.log("Error", e)
})
}
render() {
return (
<div>
<TransitionGroup>
{this.state.patients.slice(0).reverse().map(patient =>
<CSSTransition
key={patient.nom,patient.prenom}
timeout={500}
classNames="item">
<ListGroup.Item>
{patient.nom} {patient.prenom}
</ListGroup.Item>
</CSSTransition>
)}
</TransitionGroup>
</div>
)
}
}
export default Patient;
Solved. As I read in an article:
Generate a unique id for every item and use it as key when
rendering the list.
So I didn't have an unique id in my list, because the event that was broadcasting did not send id.
So in the final result in the key I should have key={patient.id} , like that every element in the list would have a unique id from database.

React - what are the steps to get data from api and render it?

I am building a site just like stackoverflow.com. I want my home page to display top questions. For that, I have sample questions on the backed. Now, I want to display only the question and tags from the questions array.
The code is in the image
I have made axios connection for that:
const instance = axios.create({
baseURL: "https://2w2knta9ag.execute-api.ap-south-1.amazonaws.com/dev", });
instance.defaults.headers.post["Content-Type"] = "application/json";
To connect it, I wrote the command: instance.get("/questions)
Now, how do I display only the question and tags??
EDIT:
On using the code given bellow, my js file now becomes:
import React from 'react';
import instance from '../../api';
class QuestionList extends React {
componentDidMount() {
instance
.get("/questions")
.then((res) => {
this.setState({ data: res.data });
});
}
render () {
const { data } = this.state;
return <div>
{
data && data.map(d => {
return <div>question: {d.question}, tags: {d.tags}</div>;
})
}
</div>
}
}
export default QuestionList;
But, this is just making my site in a loading state, and it gets hanged!!
If I understood correctly, you want to get an array only with the tags and the question. if so, you can use Array.prototype.map for this
const questions = result.map(({ question, tags }) => ({ question, tags }))
First you export the axios instance so that it can be used from other components.
Now you can send the api request in componentDidMount and update your component's state with the data.
And in render function, you just get the value from state and display.
If you are new to react, learn React Hooks and know that componentDidMount method is the best place to send api requests.
For Example:
import React from 'react';
import instance from '../../api';
class QuestionList extends React.Component {
constructor() {
super();
this.state = {
data: [],
};
}
componentDidMount() {
instance.get('/questions').then((res) => {
this.setState({ data: res.data });
});
}
render() {
const { data } = this.state;
return (
<div>
{data &&
data.map((d) => {
return (
<div>
question: {d.question}, tags: {d.tags}
</div>
);
})}
</div>
);
}
}
export default QuestionList;

Not sure if i'm using react context correcly

I've created a form in react and after some research i think that if you don't want to use an external library to manage the form, the context could be the best choice, expecially in my case where i've many nested component that compose it.
But, i'm not sure that putting a function inside my state is a good thing.
But let me give you some code:
configuration-context.js
import React from 'react'
export const ConfigurationContext = React.createContext();
ConfigurationPanel.jsx
import React, { Component } from 'react'
import { Header, Menu, Grid } from 'semantic-ui-react'
import ConfigurationSection from './ConfigurationSection.jsx'
import {ConfigurationContext} from './configuration-context.js'
class ConfigurationPanel extends Component {
constructor(props) {
super(props)
this.state = {
activeItem: '',
configuration: {
/* the configuration values */
banana: (data) => /* set the configuration values with the passed data */
}
}
}
handleItemClick = (e, { name }) => this.setState({ activeItem: name })
render() {
return (
<ConfigurationContext.Provider value={this.state.configuration}>
<Grid.Row centered style={{marginTop:'10vh'}}>
<Grid.Column width={15} >
<div className='configuration-panel'>
/* SOME BUGGED CODE */
<div className='configuration-section-group'>
{this.props.data.map((section, i) => <ConfigurationSection key={i} {...section} />)}
</div>
</div>
</Grid.Column>
</Grid.Row>
</ConfigurationContext.Provider>
)
}
}
ConfigurationItem.jsx
import React, { Component } from 'react'
import { Input, Dropdown, Radio } from 'semantic-ui-react'
import {ConfigurationContext} from './configuration-context.js'
class ConfigurationItem extends Component {
static contextType = ConfigurationContext
constructor(props) {
super(props)
}
handleChange = (e, data) => this.context.banana(data)
itemFromType = (item) =>{
switch (item.type) {
case "toggle":
return <div className='device-configuration-toggle-container'>
<label>{item.label}</label>
<Radio name={item.name} toggle className='device-configuration-toggle'onChange={this.handleChange} />
</div>
/* MORE BUGGED CODE BUT NOT INTERESTING*/
}
}
render() {
return this.itemFromType(this.props.item)
}
}
So, at the end i've a ConfigurationContext that is just a declaration, everything is inside the parent state.
The thing that i don't like is putting the banana function inside the state (it will have more logic that just logging it)
What do you think about it?
Any suggestion is appreciated.
Thanks
banana is just a regular function and you do not have to put it in the state, just do:
class ConfigurationPanel extends Component {
banana = data => console.log(data)
...
render() {
return (
<ConfigurationContext.Provider value={{banana}}>
...
}
After that you can use this.context.banana(data) as normal.

How to get meta values in reactJs?

I am working on react application.I need meta tags value(description,title,etc).I am not able to access it.I need for navigator share api.My code is:
import React, { Component } from 'react';
import { Button } from 'semantic-ui-react'
class App extends Component {
constructor(props){
super(props);
this.getOpenGraphData = this.getOpenGraphData.bind(this);
}
getOpenGraphData(property){
return document.querySelector(`meta[property="${property}"]`)
.getAttribute('content');
}
handleClick(){
navigator.share({
title: getOpenGraphData('og:title'),
text: getOpenGraphData('og:description'),
url: getOpenGraphData('og:url')
})
.then(() => {
console.log('Successfully shared');
alert("successfully shared")
})
.catch((error) => console.log('Error sharing:', error));
}
render() {
return (
<div>
<Button content='Click Here' onClick={this.handleClick.bind(this)}/>
</div>
);
}
}
export default App;
But i am not able to access meta properties.Where I am doing wrong??
I think the issue is not with selecting the meta tag, but with navigator.share() as it is an experimental feature not fully supported by all browsers, check here.
You can check if navigator is supported before calling it:
if (navigator.share) {
navigator.share({...});
}

Resources