How to hide these elements before the user uses the search - reactjs

There is a Main component, which has 4 separate components. It is necessary that these components are not visible before the user does not use the search.
The first component is responsible for displaying the weather graph, and the second for displaying the map. I do not know how to hide these two components specifically.
first component 1
import React, { useContext, useState, useEffect } from 'react';
import Chart from 'react-apexcharts';
import { Context } from '../../contex';
import './weather-graph.scss';
import { useTranslation } from 'react-i18next';
const WeatherGrapth = () => {
const { t } = useTranslation()
const {dailyForecast} = useContext(Context);
const [category, setCategory] = useState([])
const [data, setData] = useState([])
useEffect(() => {
const day = [];
const temp =[];
dailyForecast.forEach((d) => {
const unixTimestamp = d.dt;
const getTemp = Math.round(d.temp.day)
let getDay = new Date(unixTimestamp * 1000).getDate();
day.push(getDay)
temp.push(getTemp)
})
setCategory(day)
setData(temp)
}, [dailyForecast]);
return(
<>
{dailyForecast.temp &&
<div className="graph__container">
<h3 className="graph__title">{t("weekly_foreacst")}</h3>
<Chart options={{
chart: {
id: 'weather-graph'
},
xaxis: {
categories: category,
title: {
text: [t("date")],
},
},
yaxis: {
title: {
text: [t("temperature")],
},
},
}}
series={[{
name: 'temp',
data: data
}]} type="line" height={'349px'} />
</div>
}
</>
)
}
export default WeatherGrapth;
second component 2
import React, { useEffect } from 'react';
import './weather-map.scss';
import {API_KEY} from './../../apis/config';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet-openweathermap/leaflet-openweathermap.css';
import 'leaflet-openweathermap';
import { useTranslation } from 'react-i18next';
const WeatherMap = () => {
const { t } = useTranslation();
useEffect(() => {
const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18, attribution: 'copyright OpenStreetMap contributors' });
const clouds = L.OWM.clouds({showLegend: false, opacity: 0.5, appId: `${API_KEY}`});
const cloudscls = L.OWM.cloudsClassic({showLegend: false,appId: `${API_KEY}`});
const precipitation = L.OWM.precipitation({showLegend: false, appId: `${API_KEY}`});
const precipitationcls = L.OWM.precipitationClassic({showLegend: false,appId: `${API_KEY}`});
const rain = L.OWM.rain({showLegend: false,appId: `${API_KEY}`});
const raincls = L.OWM.rainClassic({showLegend: false,appId: `${API_KEY}`});
const snow = L.OWM.snow({showLegend: false,appId: `${API_KEY}`});
const pressure = L.OWM.pressure({showLegend: false,appId: `${API_KEY}`});
const pressurecntr = L.OWM.pressureContour({showLegend: false,appId: `${API_KEY}`});
const temp = L.OWM.temperature({showLegend: false,appId: `${API_KEY}`});
const wind = L.OWM.wind({showLegend: false,appId: `${API_KEY}`});
const map = L.map('map', { center: new L.LatLng(53.9, 27.5667), zoom: 5, layers: [osm] });
const baseMaps = { "OSM Standard": osm };
const overlayMaps = {
[t("clouds")]: clouds,
[t('cloudscls')]: cloudscls,
[t('precipitation')]: precipitation,
[t('precipitationcls')]: precipitationcls,
[t('rain')]: rain,
[t('raincls')]: raincls,
[t('snow')]: snow,
[t('pressure')]: pressure,
[t('pressurecntr')]: pressurecntr,
[t('temp')]: temp,
[t('wind')]: wind,
};
const layerControl = L.control.layers(baseMaps, overlayMaps,{collapsed:window.innerWidth < 768}).addTo(map);
}, []);
return(
<div className="weathermap-container">
<div id="map" style={{height: '260pt', borderRadius:'20px'}} className="map-weather"></div>
</div>
)
}
export default WeatherMap;

You can achieve that by passing down a prop
For instance
return (
<>
<div className="main-container">
{prop.visible ?
<CardWeather />
<Forecast/>
<WeatherGrapth/>
<WeatherMap/>
: ""
}
</div>
<div className="pr">weather app</div>
</>
)
}
export default Main;```
So to make it visible just pass in
```visible={true} ```
when calling the function

Related

React Quill - social media link to embed media on rich text editor

I want the react quill rich text editor able to convert link into social media, like this
link: https://www.tiktok.com/#epicgardening/video/7055411162212633903
My RTE Code
import { useCallback, useMemo, useEffect } from 'react';
import ImageResize from 'quill-image-resize-module-react';
import ReactQuill, { Quill } from 'react-quill';
import { message } from 'antd';
import { uploadFiles } from 'utils';
import 'react-quill/dist/quill.bubble.css';
import 'react-quill/dist/quill.snow.css';
import './styles.scss';
Quill.register('modules/imageResize', ImageResize);
const RichTextEditor = ({
editorState,
onChange,
readOnly = false,
setLoading = () => {}
}) => {
window.Quill = Quill;
let quillRef = null; // Quill instance
let reactQuillRef = null; // ReactQuill component
useEffect(() => {
attachQuillRefs();
}, []);
const attachQuillRefs = useCallback(() => {
if (typeof reactQuillRef.getEditor !== 'function') return;
quillRef = reactQuillRef.getEditor();
}, []);
const imageHandler = () => {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.click();
input.onchange = async () => {
const file = input.files[0];
if (file.size > 1500000)
return message.error('Image size exceeded 1.5Mb');
setLoading({ image: true });
const formData = new FormData();
formData.append('image', file);
const fileName = file.name;
const imgUrl = await uploadFiles(file, quillRef);
const range = quillRef.getSelection();
quillRef.insertEmbed(range.index, 'image', imgUrl, 'user');
let existingDelta = quillRef.getContents();
const indexOf = existingDelta.ops.findIndex((eachOps) => {
return eachOps.insert?.image === imgUrl;
});
const selectedOps = existingDelta.ops[indexOf];
if (indexOf !== -1) {
selectedOps.attributes = {};
selectedOps.attributes = { alt: fileName };
}
quillRef.setContents(existingDelta);
setLoading({ image: false });
};
};
const modules = useMemo(
() => ({
toolbar: {
container: [
[{ header: [1, 2, 3, 4, 5, 6, false] }],
['bold', 'italic', 'underline'],
[{ list: 'ordered' }, { list: 'bullet' }],
[{ align: [] }],
['link', 'image'],
['clean'],
[{ color: [] }]
],
handlers: {
image: imageHandler
}
},
imageResize: {
modules: ['Resize', 'DisplaySize']
}
}),
[]
);
return (
<div className="react-quill-wrapper">
<ReactQuill
readOnly={readOnly}
theme={readOnly ? 'bubble' : 'snow'}
ref={(e) => {
reactQuillRef = e;
}}
value={editorState}
modules={modules}
placeholder="Add content of your article!"
onChange={onChange}
/>
</div>
);
};
export { RichTextEditor };
const [editorState, setEditorState] = useState('');
<RichTextEditor
editorState={editorState}
onChange={setEditorState}
setLoading={setLoading}
/>
called by parent like this
I've been working on this for almost a week, I really need help
I expected to have an string HTML output, like this library or image above
My attempts:
Get the social media url typed by user based on link, use that typed link to determined what social media, and use react-social-media-embed to give me an output link image above.
I belive(maybe) that the output from react-social-media-embed is jsx, and I need to convert it to html, and parsed it to string.

Swipeable react component always starts from same [0.0] position

I'm trying to develop a swipe component using React w/ Redux and hammerjs. The problem is that each time I move my component the position.x and position.y start from [0,0] and not from the current state they are at.
Here's the code:
import React, { useState, useEffect } from 'react';
import Hammer from 'hammerjs';
import WeatherForecast from './WeatherForecast';
const SwipeableCard = ({ children }) => {
const [gesture, setGesture] = useState(null);
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
const element = document.getElementById('swipeable-card');
const hammer = new Hammer(element);
hammer.on('pan', (event) => {
setPosition({
x: event.deltaX + position.x,
y: event.deltaY + position.y,
});
});
setGesture(hammer);
return () => {
hammer.off('pan');
setGesture(null);
};
}, []);
return (
<div
id="swipeable-card"
className="App-swipeable"
style={{
transform: `translate(${position.x}px, ${position.y}px)`,
}}
>
<WeatherForecast />
</div>
);
};
export default SwipeableCard;

want to give average height to wave in wavesurfer

import React, { useEffect, useRef, useState } from "react";
import WaveSurfer from "wavesurfer.js";
const formWaveSurferOptions = ref => ({
container: ref,
barWidth:1,
waveColor: "#eee",
progressColor: "OrangeRed",
cursorColor: "OrangeRed",
barRadius: 10,
responsive: true,
height: 200,
barGap:0,
pixelRatio: 5,
barMinHeight:100,
normalize: true,
partialRender: true
});
export default function Waveform({ url }) {
const waveformRef = useRef(null);
const wavesurfer = useRef(null);
const [playing, setPlay] = useState(false);
const [volume, setVolume] = useState(0.5);
useEffect(() => {
setPlay(false);
const options = formWaveSurferOptions(waveformRef.current);
wavesurfer.current = WaveSurfer.create(options);
wavesurfer.current.load(url);
wavesurfer.current.on("ready", function() {
if (wavesurfer.current) {
wavesurfer.current.setVolume(volume);
setVolume(volume);
}
});
return () => wavesurfer.current.destroy();
}, [url]);
const handlePlayPause = () => {
...
};
const onVolumeChange = e => {
...
};
return (
<div>
<div id="waveform" ref={waveformRef} />
<div className="controls">
<button onClick={handlePlayPause}>{!playing ? "Play" : "Pause"}</button>
<input
...
/>
<label htmlFor="volume">Volume</label>
</div>
</div>
);
}
The problem in this is that, i want to set the height of the minpeak of the wave and also give the height an average that at this level it does not go up. i tried the minHeightBar, but unfortunatelydoes't work at all, I have connected the two images for better understanding, so if any one knows this so please help, thankyou :)

React calls api thousands of times inside a useEffect

I am building a ToDoList with React and a Django rest Api but I am also using a Datepicker to render all the tasks for the day by the date created. But every time the site loads the api is called thousands of times. The goal would be to only render the tasks for the specific day when the date is changed or a new task for the day is added and not call the backend constalnly the problem seams to lay at the ToDoList because evertwhere else the props.date is only called once and not in a loop.
import React, { useState } from 'react'
import 'date-fns'
import Grid from '#material-ui/core/Grid'
import DateFnsUtils from '#date-io/date-fns'
import{
MuiPickersUtilsProvider,
KeyboardTimePicker,
KeyboardDatePicker
} from '#material-ui/pickers'
import TodoForm from '../ToDo/TodoForm'
function Datepicker() {
const initialDate = new Date(Date.now())
const [selectDate, setSelectDate] = useState(
`${initialDate.getFullYear()}-${initialDate.getMonth()+1}-${initialDate.getDate()}`
)
const handleDateChange = (date) =>{
setSelectDate(`${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`)
}
return (
<div>
<div>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Grid container justify='space-around'>
<KeyboardDatePicker
disableToolbar
varient='inline'
format='MM/dd/yy'
margin='normal'
id='date-picker'
label='Pick your Date'
value={selectDate}
onChange={handleDateChange}
KeyboradButtonProps={{
'aris-label': 'change date'
}}
/>
</Grid>
</MuiPickersUtilsProvider>
</div>
<div>
<TodoForm date={selectDate}/>
</div>
</div>
)
}
export default Datepicker
import React, { Component, useState,useEffect } from 'react'
import Select from 'react-select'
import { apiTaskCreate } from './lookup'
import { ActionBtn } from './buttons'
import TodoList from './TodoList'
function TodoForm(props) {
const [newTasks, setNewTasks] = useState([])
const [taskname, SetTaskname] = useState('')
const [Importants, setImportants] = useState({})
const [TimeComplete, setTimeComplete] = useState({})
const handleChange = e => {
SetTaskname(e.target.value)
}
function onChangeImportants(value){
setImportants(value.value)
}
function onChangeTimeComplete(value){
setTimeComplete(value.value)
}
const handleSubmit = e =>{
e.preventDefault()
SetTaskname('')
let tempNewTasks = [...newTasks]
apiTaskCreate(taskname,Importants,TimeComplete,(response, status)=>{
// console.log(response, status)
if (status === 201){
tempNewTasks.unshift(response)
setNewTasks(tempNewTasks)
} else {
console.log(response)
alert("an error accourd")
}
})
}
const Importants_options = [
{ value: '1', label: 1 },
{ value: '2', label: 2 },
{ value: '3', label: 3 },
{ value: '4', label: 4 },
{ value: '5', label: 5 },
]
const Time_options = [
{ value: '1', label: 30 },
{ value: '2', label: 60 },
{ value: '3', label: 90 },
{ value: '4', label: 120 },
{ value: '5', label: 150 },
{ value: '6', label: 180 },
]
return (
<div className={props.className}>
<div className='col-11 mb-3'>
<form className='todo-form mb-3' onSubmit={handleSubmit}>
<input type='text' value={taskname} placeholder='Task Name'
name='task_name' className='todo-input' onChange={handleChange}></input>
<Select onChange={onChangeImportants} options={Importants_options} placeholder="Importants Score"/>
<Select onChange={onChangeTimeComplete} options={Time_options} placeholder="Time to complete"/>
<button className='btn btn-primary'>Submit</button>
<ActionBtn action={{type: 'optimize', display:"Optimize"}}/>
</form>
</div>
<div className='container'>
<TodoList newTasks={newTasks} {...props}/>
</div>
</div>
)
}
export default TodoForm
import React, {useState, useEffect} from 'react'
import { apiTaskList } from './lookup'
import Task from './Task'
function TodoList(props) {
const [tasksInit, setTasksInit] = useState([])
const [tasks, setTasks] = useState([])
const [tasksDidSet, setTasksDidSet] = useState(false)
const initialDate = new Date(Date.now())
const [date, setDate] = useState("2021-04-12")
// `${initialDate.getFullYear()}-${initialDate.getMonth()+1}-${initialDate.getDate()}`
useEffect( () =>{
const final = [...props.newTasks].concat(tasksInit)
if (final.length !== tasks.length) {
setTasks(final)
}
}, [props.newTasks, tasks, tasksInit])
useEffect(() => {
if (tasksDidSet === false) {
const handleTasksListLookup = (response, status) => {
if (status === 200) {
setTasksInit(response)
setDate(props.date)
console.log(date)
}
}
apiTaskList("admin", date ,handleTasksListLookup)
}
}, [tasksInit, setTasksDidSet, setTasksDidSet, date])
return tasks.map((item, index)=>{
return <Task task={item} className='d-flex p-2 justify-content-between border bg-white text-dark' key={`${index}-${item.id}`}/>
})
}
export default TodoList;
import { backendlookup } from "../lookup/lookup";
export function apiTaskCreate(newTask_Name,newImportans_Score,newTime_to_complete,callback) {
backendlookup('POST', 'create',callback, {
Task_name: newTask_Name,
Importants_Score: newImportans_Score,
Time_to_Finish: newTime_to_complete,
})
}
export function apiTaskList(username,date,callback) {
let endpoint = 'tasks'
if (date){
endpoint = `tasks?username=${username}&date=${date}`
}
backendlookup('GET', endpoint ,callback)
}
export function apiPartyActionOptimize(action,callback) {
backendlookup('POST', 'action-optimize',callback, {action:action})
You are adding a dependency to useEffect which itself is being updated inside it. If you do so, your useEffect execution will go into an infinite loop.
You can make use of functional version of setState to update the tasks state.
Your updated code will look as follows
useEffect( () =>{
const final = [...props.newTasks].concat(tasksInit);
setTasks(tasks => {
if (final.length !== tasks.length) {
return final;
}
return tasks
});
}, [props.newTasks, tasksInit])
useEffect(() => {
if (tasksDidSet === false) {
const handleTasksListLookup = (response, status) => {
if (status === 200) {
setTasksInit(response);
setDate(props.date);
}
}
apiTaskList("admin", date ,handleTasksListLookup)
}
}, [setTasksInit, props.date, tasksDidSet])
When you call the setTasks method inside the useEffect function it updates the tasks value and because you have the tasks variable as one of the dependencies in the useEffect callback, the API gets called indefinitely. Remove tasks from the useEffect dependency and it should work.

How to test function component with a react-data-grid

I have created a data grid with react using React-data-grid (link)
My code is as follows:
import React, { useState } from "react";
import ReactDataGrid from 'react-data-grid';
const ROW_COUNT = 20;
const MIN_WIDTH = 100;
const defaultColumnProperties = {
resizable: true,
sortable: true
};
const columns = [
{
key: "eventTypeNameI18n",
name: "Type",
},
{
key: "nameI18n",
name: "Name",
width: 160
},
{
key: "dateCreated",
name: "Time",
width: 220
},
{
key: "locationNameI18n",
name: "Location",
width: 200
}
].map(col => ({...col, ...defaultColumnProperties}));
const sortRows = (initialRows, sortColumn, sortDirection) => rows => {
const comparer = (a, b) => {
if (sortDirection === "ASC") {
return a[sortColumn] > b[sortColumn] ? 1 : -1;
}
else if (sortDirection === "DESC") {
return a[sortColumn] < b[sortColumn] ? 1 : -1;
}
};
return sortDirection === "NONE" ? initialRows : [...rows].sort(comparer);
};
function DataGrid({initialRows}) {
const [rows, setRows] = useState(initialRows);
return (
<ReactDataGrid
id="EventDataGrid"
columns={columns}
rowGetter={i => rows[i]}
rowsCount={ROW_COUNT}
minColumnWidth={MIN_WIDTH}
onGridSort={(sortColumn, sortDirection) =>
setRows(sortRows(initialRows, sortColumn, sortDirection))
}
/>
);
}
export default DataGrid;
I am new to writing unit tests and have been writing very basic unit tests as of recent. I am wondering what is the best way to test the onGridSort method using Jest/Enzyme
In my tests I currently have the following:
import React from 'react';
import ReactDOM from 'react-dom';
import Enzyme, {mount} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import EventsGrid from '../EventsGrid';
import sampleData from './sampleData/transformedEventSample';
Enzyme.configure({adapter: new Adapter()});
describe('Tests for <EventDataGrid/>', () => {
it('sort data grid by ascending ', () => {
const wrapper = mount(<EventsGrid initialRows={sampleData}/>);
const instance = wrapper.instance();
jest.spyOn(instance, 'sortRows');
const column = 'eventTypeNameI18n';
const sortDirection = 'ASC';
wrapper.find('#EventDataGrid').at(1).prop('onGridSort')(column, sortDirection);
expect(instance.sortRows).toHaveBeenCalled();
});
it('sort data grid by descending', () => {
const wrapper = mount(<EventsGrid initialRows={sampleData}/>);
const instance = wrapper.instance();
jest.spyOn(instance, 'sortRows');
const column = 'eventTypeNameI18n';
const sortDirection = 'DESC';
wrapper.find('#EventDataGrid').at(1).prop('onGridSort')(column, sortDirection);
expect(instance.sortRows).toHaveBeenCalled();
});
});
I want to test to make sure that the grid is ordered correctly (ordered by ascending/descending)

Resources