Difference between this two js in react - reactjs

I start to learn React JS and anyone can explain me the difference between those two files? Both of them do the same thing.
First JS
import React, { useEffect, useState } from 'react'
import Product from './Product';
import './Today.css';
import { Link } from 'react-router-dom';
import { render } from '#testing-library/react';
export default class Today extends React.Component {
state = {
loading : true,
fixture : null
};
async componentDidMount() {
const OPTIONS = {
method : 'GET',
headers : {
'X-RapidAPI-Host' : 'api-football-v1.p.rapidapi.com',
'X-RapidAPI-Key' : '###'
}
};
const url = 'https://api-football-v1.p.rapidapi.com/v2/fixtures/date/2020-07-18';
const response = await fetch(url,OPTIONS);
const fixtures = await response.json();
this.setState({ fixture: fixtures.api.fixtures, loading: false});
const teamData = fixtures.api && fixtures.api.fixtures > 0 ? fixtures.api.fixtures : [];
console.log(this.state);
}
render() {
return (
<div className="today">
{this.state.loading || !this.state.fixture ? (
<div><img src=""/></div>
) : (
<div>
<div>
{this.state.fixture.slice(0,10).map(fixtureToday => (
<div>{fixtureToday.homeTeam.team_name}</div>
))}
</div>
</div>
)}
</div>
)
}
}
Second one
import React, { useState, useEffect } from 'react';
import './AnotherDay.css';
import { Link } from 'react-router-dom';
function AnotherDay() {
useEffect(() => {
fetchItems();
},[]);
const OPTIONS = {
method : 'GET',
headers : {
'X-RapidAPI-Host' : 'api-football-v1.p.rapidapi.com',
'X-RapidAPI-Key' : '###'
}
};
const [fixtures, setItems] = useState([]);
const fetchItems = async () => {
const data = await fetch(
'https://api-football-v1.p.rapidapi.com/v2/fixtures/date/2020-07-18' , OPTIONS
);
const fixtures = await data.json();
const teamData = fixtures.api && fixtures.api.fixtures.length > 0 ? fixtures.api.fixtures : [];
console.log(teamData);
setItems(teamData);
}
return (
<div>
{fixtures.slice(0,10).map(fixture => (
<div>{fixture.homeTeam.team_name}</div>
))}
</div>
);
}
export default AnotherDay;
And in the App.js I have
import React from 'react'
import './Today.css';
import { Link } from 'react-router-dom';
import Today from './Today ';
import AnotherDay from './EvenimenteMaine';
function TodayEvents() {
return (
<div className="today">
<div className="todayEvents">
<Today />
</div>
<div className="anotherDayEvents">
<AnotherDay />
</div>
</div>
)
}
export default TodayEvents
I have the same result in the both divs. My question is, what is the difference? The first one is a class and the second one is a function?
Which one is the correct way?
Thanks, maybe is a noob question but I'm new to learning React.

The first example is a class component the second one is a functional component. React development is moving away from classes toward the functional components. useEffect is supposed to replace several life cycle functions from class components.
Two things to look into functional components and class components. The second set of things to look up is life cycle functions and functional component hooks.
Here is a link that will explain at a high level the differences.
https://dev.to/danielleye/react-class-component-vs-function-component-with-hooks-13dg

Related

Trying to show a random picture from Unsplash

Hi this is my first React app im trying to build.
I'm trying to show a random image in React but i can't get
the image to show.
import React from 'react';
function ImageList(props) {
console.log(props);
return (
<div><img src={props} alt="cat"/></div>
);
}
export default ImageList;
the props looks like this:
props: "https://images.unsplash.com/photo-1568152950566-c1bf43f4ab28?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNTkxNzd8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NjE3NTY3NTc&ixlib=rb-1.2.1&q=80&w=400"
When i inspect the img it says object Object.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css'
import ImageList from './ImageList';
const App = () => {
const [cats, setCats] = useState("");
async function onSearchSubmit(term) {
const response = await axios.get('https://api.unsplash.com/photos/random/',{
params: { query: term},
headers:{
Authorization: 'Client-ID //here i just where i put my key in '
}
});
setCats(response.data.urls.small);
}
return(
<div className='App'>
<button onClick={() => {onSearchSubmit("cat")} }>
Show a cat picture
</button>
<ImageList props = {cats}/>
</div>
);}
export default App;
This is the rest of the code.
I am thankful for your help. Cheers!
props it's just the name of your prop.
Look at this row:
<ImageList props = {cats}/>
You shouldn't use the props name for your props. Use some meaningful name instead, like cats
<ImageList cats = {cats}/>
// And in ImageList
const ImageList = ({cats}) => {
// do something with cats. Now it must be a string
}
OR
// props is an object
const ImageList = (props) => {
const cats = props.cats
// do something with cats. Now it must be a string
}

How to use variable from script A in srcript B typescript?

I want to get variable from other script to build the next part of the page on the basis of this data.
This is code to get data from API:
import Axios from "axios";
import React from "react";
export default class PersonList extends React.Component {
state = {
dataURL: [], //from this variable I want get data
};
componentDidMount() {
Axios.get(
"https://g.tenor.com/v1/search?q=" +
"mems" +
"&key=" +
"MY_TENOR_API_KEY" +
"&limit=" +
"1"
).then((res) => {
this.state.dataURL = res.data;
this.setState({ dataURL });
console.log(this.state.dataURL);
});
}
render() {
return;
}
}
Here I want to dynamically import the script and try to get access to variable from other script
import { useState } from "react";
import styles from "../styles/Form.module.scss";
function Form() {
const [results, setResults] = useState();
return (
<div className={styles.container}>
<div className={styles.form}>
<input
type="button"
onClick={async (e) => {
const { value } = e.currentTarget;
const Fuse = (await import("../pages/api/tenor")).default;
const fuse = new Fuse(state); //I got there an error: "Cannot find name 'state'.ts(2304)"
setResults(fuse.search(value));
}}
/>
</div>
</div>
);
}
export default Form;
Basically, if you want to access a component's data from a different component you have a few options you can choose from.
Send that data as a prop.
(only relevant if the 2nd component is a child/grand-child/etc.. of the 1st component)
Manage a "global state" (a single source containing the app's relevant data).
This can be achieved via 3rd-party libraries (Redux / MobX / etc..)
Or even via React's built-in ContextAPI.
Use a shared hook containing the state which can then be accessed from other components.
(only relevant for functional components)
IMO, the simplest option is the 3rd, but it will require turning PersonList into a functional hook.
An example should look like this:
// Shared "PersonList" hook.
import Axios from "axios";
import React, { useState } from "react";
export function usePersonList() {
const [dataURL, setDataURL] = useState([]);
useEffect(() => {
Axios.get(
"https://g.tenor.com/v1/search?q=" +
"mems" +
"&key=" +
"MY_TENOR_API_KEY" +
"&limit=" +
"1"
).then(res => setDataURL(res.data));
}, []);
return dataURL;
}
// Form.tsx
import { useState } from "react";
import styles from "../styles/Form.module.scss";
function Form() {
const [results, setResults] = useState();
const dataURL = usePersonList();
return (
<div className={styles.container}>
<div className={styles.form}>
<input
type="button"
onClick={async (e) => {
const { value } = e.currentTarget;
const Fuse = (await import("../pages/api/tenor")).default;
const fuse = new Fuse(dataURL);
setResults(fuse.search(value));
}}
/>
</div>
</div>
);
}
export default Form;
You can try React Redux or useReducer to share variable between components.

Creating default chat groups in Sendbird using React

We've integrated a chat UI into a project using Sendbird. The chat interface is now working and what I am trying to do now is implement a feature where there are 2 default chat groups as shown in the mockup below:
I have already gone through the docs but I can’t seem to find the information I need to implement this feature. Can this be implemented? can someone guide me to the right direction, please?
import React, { useEffect, useState, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';
import 'sendbird-uikit/dist/index.css';
import { App as SendBirdApp, } from 'sendbird-uikit';
import { getModuleState as getAuthModuleState } from 'services/auth';
import colorSet from './styled/chatPalette';
import { Chat, ChatContainer, List } from './styled/chatPage';
import ChatGroups from './ChatGroups';
function ChatPage(props) {
const { theme } = props;
const history = useHistory();
const authState = useSelector(getAuthModuleState);
const userId = authState.username;
const nickname = authState.username;
const appId = authState.sendbirdData.appId;
const accessToken = authState.sendbirdData.accessToken;
useEffect(() => {
if (!userId || !nickname) {
console.error('Error, empty userId or nickname');
}
}, [userId, nickname, history]);
return (
<ChatContainer>
<SendBirdApp
appId={appId}
userId={userId}
nickname={nickname}
colorSet={colorSet}
/>
</ChatContainer>
);
}
export default ChatPage;
you can use the <SendbirdProvider> component and provide your custom channel preview component (let's say <ChannelPreview>) inside the <ChannelList> component.
Within your custom preview component (<ChannelPreview>) you can choose wether or not to show a specific channel based on its member count (channel.memberCount) as shown below:
import { Channel, ChannelList, SendBirdProvider } from 'sendbird-uikit';
import 'sendbird-uikit/dist/index.css';
import { useState } from 'react';
const CHANNEL_PREVIEW_MODES = [
'1-on-1',
'Group'
]
function ChannelPreview({channel, previewMode}) {
if (
(channel.memberCount <=2 && previewMode !== CHANNEL_PREVIEW_MODES[0]) ||
(channel.memberCount > 2 && previewMode !== CHANNEL_PREVIEW_MODES[1])
) {
return null
}
return (
<div key={channel.url}>
<img height="20px" width="20px" src={channel.coverUrl}/>
{channel.url}
</div>
)
}
function App() {
const [previewMode, setPreviewMode] = useState(CHANNEL_PREVIEW_MODES[0])
const [currentChannel, setCurrentChannel] = useState(null);
return (
<div className="App">
<SendBirdProvider
userId='<USER_ID>'
appId='<APP_ID>'
>
<div>
{CHANNEL_PREVIEW_MODES.map(mode =>
<label className="preview-mode-radio">{mode}
<input
type='radio'
value={mode}
name='preview-mode'
onChange={() => setPreviewMode(mode)}
checked={previewMode === mode}
/>
</label>
)}
</div>
<ChannelList
renderChannelPreview={({channel}) => <ChannelPreview channel={channel} previewMode={previewMode} />}
onChannelSelect={channel => setCurrentChannel(channel)}
/>
<Channel channelUrl={currentChannel?.url} />
</SendBirdProvider>
</div>
);
}
export default App;

converting react class to functional component with refs

I'm trying to use a class example from a stackblitz file and convert it to a functional component.
I don't understand how the ref works, or where the event and args that are being used in the onTyping function are coming from. Can anyone explain where those are defined and how I'd translate this to a functional component?
import { render } from 'react-dom';
import './index.css';
import * as React from 'react';
import { AutoCompleteComponent } from '#syncfusion/ej2-react-dropdowns';
import { SampleBase } from './sample-base';
import * as data from './dataSource.json';
export class Default extends SampleBase {
constructor() {
super(...arguments);
this.temp = 'sportsData';
// define the array of string
this.sportsData = data[this.temp];
}
onTyping(args) {
console.log(event.target.value);
}
render() {
return (<div id='combodefault' className='control-pane'>
<div className='control-section'>
<div className='col-lg-12 control-wrappers'>
<div id='default'>
<AutoCompleteComponent id="games" dataSource={this.sportsData} ref={(AutoComplete) => { this.listObj = AutoComplete; }} placeholder="e.g. Basketball" actionBegin={this.onTyping}/>
</div>
</div>
</div>
</div>);
}
}
render(<Default />, document.getElementById('sample'));
anything in the constructor will need to be translated to useState:
this.temp = 'sportsData';
// define the array of string
this.sportsData = data[this.temp];
becomes:
const[temp, setTemp] = useState('sportsData');
const[sportsData, setSportsData] = useState(data[temp]);
setTemp and setSportsData are functions that you use to set the state variable temp and sportsData respectively. For example, the following will set temp to 'NFSSportsData'.
setTemp('NFLSportsData');
As for the ref, you can use the hook useRef.
const listObj = useRef(null);
for component life cycle method componentDidMount, you can use the following convention.
useEffect(()=>{
// your code
}, [])
the empty bracket [] signifies only to run the code once when the component mounts. If you want to code listen to a state variable, and runs every time the variable changes, you can do the following:
useEffect(()=>{
// your code
}, [sportsData])
This code above will run every time state variable sportsData changes.
I don't think there's a way to extend a functional component like you are doing with SampleBase. Looking at the SampleBase class, it's just running a function in the lifecycle component componentDidMount. You can do something like the following:
rendereComplete() {
/**custom render complete function */
}
useEffect(()=>{
setTimeout(() => {
this.rendereComplete();
},[]);
To tie is all together, you have something like the following:
import './index.css';
import * as React from 'react';
import { AutoCompleteComponent } from '#syncfusion/ej2-react-dropdowns';
import * as data from './dataSource.json';
export const Default = ()=> {
const [temp, setTemp] = React.useState('sportsData');
const [sportsData, setSportsData] = useState(data[this.temp]);
const listObj = useRef(null);
const onTyping = (args)=>{
console.log('arg =', args);
}
const rendereComplete() {
/**custom render complete function */
}
useEffect(()=>{
setTimeout(() => {
rendereComplete();
},[]);
return (<div id='combodefault' className='control-pane'>
<div className='control-section'>
<div className='col-lg-12 control-wrappers'>
<div id='default'>
<AutoCompleteComponent id="games" dataSource={sportsData} ref={(AutoComplete) => { listObj = AutoComplete; }} placeholder="e.g. Basketball" actionBegin={onTyping}/>
</div>
</div>
</div>
</div>);
}

React - Wait for complex method to finish before rendering

I'm trying to display a dashboard component, crunching a lot of data fetched from my redux store. This component takes a lot of time to render, mainly because of a single complex method.
Is it possible to render some kind of loader or placeholder while this method is processing ?
I tried doing so by using ComponentDidMount, but it seems like, because the method is part of my render() method, it will always be triggered first-hand.
Yes! Check out this tutorial.
Loader:
import React, {Component} from 'react';
const asyncComponent = (importComponent) => {
return class extends Component {
state = {
component: null
}
componentDidMount() {
importComponent()
.then(cmp => {
this.setState({component: cmp.default});
});
}
render() {
const C = this.state.component;
return C ? <C {...this.props}/> : null;
}
}
};
export default asyncComponent;
Usage:
import React from 'react';
import asyncComponent from '../../hoc/asyncComponent';
const AsyncButton = asyncComponent(() => {
return import('../Button');
});
const container = () => {
return (
<div>
<h1>Here goes an async loaded button component</h1>
<AsyncButton/>
</div>
);
};
export default container;
or check out this library.

Resources