Passing props using userouter on Next.js - react-hooks

I've been following this guide on how to render props from my sidebar to my title header based on this links:
Dynamic Navigation in Next.js
But it doesnt show up on my title component
Here is my current settings. Basically I wanted to change the title on my header based on the sub-url that were defined in my arrays
From sidebar.tsx
import { navItems } from "../../static/NavItems";
const Sidebar = () => {
const [activeIcon, setActiveIcon] = useState("");
const router = useRouter();
return (
<Wrapper>
<LogoContainer>
<Logo>
<Image src={logo} alt="Logo" width={200} />
</Logo>
</LogoContainer>
<NavItemsContainer>
{navItems.map((nav, i) => (
<NavItem key={i} onClick={() => setActiveIcon(nav.title)}>
<NavIcon style={{ color: nav.title === activeIcon && "#3773f5" }}>
{nav.icon}
</NavIcon>
<NavTitle>
<Link as={nav.as} href={nav.path}>
{nav.title}
</Link>
</NavTitle>
</NavItem>
))}
</NavItemsContainer>
</Wrapper>
);
};
from title component
import { useRouter } from "next/router";
const Title = ({ title }) => {
const router = useRouter();
return <div>{{router.pathname === "/" ? title : ""}</div>;
};
So in my header, I've just import the component and pass it as a props like this
import { Title } from '../title.tsx';
const Header = ({ title }) => {
return (
<Title title={title} />
)
is there anything that I missed here?

Related

React-Bootstrap dynamic Image rendering

I am trying to display profile pic by calling the path and file name from database
Profile Image is not loading is it the path?
using json server local test.
Image is saved in folder ../src/image/
json data
image: "..image/pic.jpg"
import { Card, ListGroup } from "react-bootstrap";
import { useParams, useHistory } from "react-router-dom";
import useFetch from "./useFetch";
const MemberProfile = () => {
const { id } = useParams();
const {
data: member,
error,
isLoading,
} = useFetch("http://192.168.0.23:8000/members/" + id);
const history = useHistory();
const handleClick = () => {
fetch("http://192.168.0.23:8000/members/" + member.id, {
method: "DELETE",
}).then(() => {
history.push("/");
});
};
return (
<div className="memberProfile">
{isLoading && <div>Loading...</div>}
{error && <div>{error}</div>}
{member && (
<Card style={{}}>
<Card.Img variant="top" src={member.image} />
<Card.Body>
<Card.Title>
<h2>
<strong>
Profile - {member.name} {id}
</strong>
</h2>
</Card.Title>
<Card.Text>
<pre className="acordnBody">
Gender : {member.gender} <hr />
Phone : {member.tel} <hr />
E-mail : {member.email} <hr />
Address : {member.address}
</pre>
</Card.Text>
</Card.Body>
</Card>
)}
</div>
);
};
export default MemberProfile;

Todo list refreshing there is a list item with empty name and buttons

When I'm refreshing or first opening there is a list item with empty name and its buttons. Moreover i can't disappear the empty line when i'm using && this in todolist still shows.when im console.log(todos) i got array with 1 item on it.
How can i solve this problem?
const App = () => {
const [todos, setTodos] = useState([{
userInput: null,
isDone: false,
}])
const addItem = (userInput) => {
const newTodos = [...todos, {userInput}]
setTodos(newTodos)
}
const markItem = index =>{
const newTodos = [...todos];
newTodos[index].isDone = true;
setTodos(newTodos);
}
const removeItem = index => {
const newTodos = [...todos];
newTodos.splice(index,1);
setTodos(newTodos)
}
return (
<div className=>
<Calender />
<TodoInput addItem={addItem} />
{(todos?.length > 0 ) && <TodoList todos={todos} removeItem={removeItem} markItem={markItem} />}
</div>
);
}
export default App;
const TodoList = ({ todos,removeItem,markItem }) => {
return (
<div>
<ul>
{todos?.map((todo,index) => {
return (
<li key={index} >
<TodoItem todo={todo} index={index} removeItem={removeItem} markItem={markItem} />
</li>
)
})}
</ul>
</div>
)
}
const TodoItem = ({todo,index,removeItem,markItem}) => {
return (
<div>
<span className={(todo.isDone ? "line-through" : "")}>{todo.userInput}</span>
<div>
<button onClick={()=>markItem(index)}>✔</button>
<button onClick={()=>removeItem(index)}>X</button>
</div>
</div>
)
}
export default TodoItem
Why there is empty task like in the image:
You have assigned 1 item in useState
const [todos, setTodos] = useState([{
userInput: null,
isDone: false,
}])
You should declare it empty
const [todos, setTodos] = useState([])

Issue with displaying Chartjs annotation elements in Nextjs

I am transferring my CRA to a Nextjs and I am having a bit of an issue with anything that uses the <canvas> element. The charts and data are mostly there, but my annotations are now missing from the charts. I have tried importing everything with the dynamic function for the parent element, but it still seems to not show the missing features.
I am also seeing some weird things happening on an arcgis map which is not visualizing 3d elements on a <canvas>. So my guess is that this has something with the way that canvas or d3 interact with the browser.
// parent component
import moment from 'moment-timezone';
import React, { useRef } from 'react';
import {
Chart as ChartJS,
LinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
Legend,
Tooltip,
} from 'chart.js';
// import { Chart } from 'react-chartjs-2';
import { ArrowRight } from '../../icons/ArrowRight';
import Link from 'next/link';
import { chartOptions } from '../../lib/chartOptions';
import dynamic from 'next/dynamic';
const Chart = dynamic((): any => import('react-chartjs-2').then((m: any) => m.Chart), {
ssr: false,
});
ChartJS.register(
LinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
Legend,
Tooltip,
);
export const MarkupCard = ({ item }: any) => {
const chartRef = useRef();
const userName = item.user_id.split('#')[0];
return (
<div className="w-2/3 pb-10 mx-auto border-2 border-blue items-center rounded-lg my-4 py-4 flex flex-row justify-between">
<div className="w-full text-left pl-4 pb-6 h-72">
<div className="w-full flex flex-row justify-between">
<h2 className="text-lg font-bold">{userName} Marked up a chart</h2>
<div className=" w-1/3 text-right pr-4">
<h2>
{moment(item.created_at)
.tz(process.env.NEXT_PUBLIC_TIMEZONE ?? '')
.format('MM-DD-YYYY hh:mm:ss a')}
</h2>
</div>
</div>
<h2>Route: {item.routeLongName}</h2>
<Chart
style={{ height: '100px', width: '99%' }}
ref={chartRef}
plugins={item.details.options.plugins}
className="trips-chart"
type="line"
options={chartOptions(item.details.options, item.details.annotations)}
data={item.details.chartData}
/>
</div>
<Link href={`/app/markupDetail/${item.id}`}>
<button className="mx-6 h-full flex">
<ArrowRight />
</button>
</Link>
</div>
);
};
// chart component
import React, { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import { supabase } from '../../client';
import { actions } from '../../store';
import { SocialNote } from '../../types';
import { Card } from './Card';
const SocialFeed = () => {
const [feed, setFeed] = useState<SocialNote[]>([]);
const dispatch = useDispatch();
const loadPage = async () => {
dispatch(actions.setLoaded(true));
const { data, error } = await supabase
.from('notes')
.select('*')
.order('last_update', { ascending: false });
if (data) {
setFeed(data);
console.log(data);
return data;
} else {
return error;
}
};
useEffect((): (() => void) => {
loadPage();
return () => supabase.removeAllSubscriptions();
}, []);
return (
<div className="w-full mx-auto overflow-y-auto">
{feed.map((item, key) => (
<Card key={key} item={item} />
))}
</div>
);
};
export default SocialFeed;
// chartoptions.js
export const chartOptions: any = (options: any, annotations: any) => {
const { title } = options;
const { tooltip } = options.plugins;
return {
title,
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index' as const,
intersect: false,
},
plugins: {
annotation: { annotations: annotations },
tooltip,
legend: {
position: 'top' as const,
},
title,
},
};
};
// next.config.js
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = nextConfig
CRA
Nextjs
Turns out I just needed to register Annotations in ChartJS.register()
This was not the case for React, but was required for Nextjs
import Annotation from 'chartjs-plugin-annotation';
ChartJS.register(
Annotation,
LinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
Legend,
Tooltip,
);

Filter features within map view React-Map-gl React Hooks

I'm quite new to React and JavaScript, am trying to write a queryRenderedFeatures filter for my React Hooks project using React-Map-gl.
The project has a huge list of data, and what I'd like to do is only filtering the data that appears within the map view. As this example shows on Mapbox-gl-js: https://docs.mapbox.com/mapbox-gl-js/example/filter-features-within-map-view/?q=geojson%20source&size=n_10_n
From the React-Map-gl's documentation: https://uber.github.io/react-map-gl/docs/api-reference/static-map#getmap
It says that you will be able to use queryRenderedFeatures as a method for a static map, but the way I've added it seems wrong... And there are not many resources online :/
Any help would be appreciated! :)
export default function Map() {
const [data, setData] = useState()
const [viewport, setViewport] = useState({
latitude: -28.016666,
longitude: 153.399994,
zoom: 12,
bearing: 0,
pitch: 0
})
const mapRef = useRef()
useEffect(() => {
fetch('../data.json')
.then(res => res.json())
.then(res => setData(res))
},[])
function features () {
mapRef.current.queryRenderedFeatures( { layers: ['ramps'] })
}
function filterRamps (e) {
data.features.filter(feature => {
return feature.properties.material === e.target.value
})
}
const handleClick = () => {
setData(filterRamps())
}
if (!data) {
return null
}
return (
<div style={{ height: '100%', position: 'relative' }}>
<MapGL
ref={mapRef}
{...viewport}
width="100%"
height="100%"
mapStyle="mapbox://styles/mapbox/dark-v9"
onViewportChange={setViewport}
mapboxApiAccessToken={Token}
queryRenderedFeatures={features}
>
<Source type="geojson" data={data}>
<Layer {...dataLayer} />
</Source>
</MapGL>
<Control
data={data}
onClick={handleClick}
/>
</div>
)
}
You need something like:
...
const mapRef = useRef()
...
<MapGL
ref={mapRef}
onClick={e => {
const features = mapRef.current.queryRenderedFeatures(e.geometry.coordinates, { layers: ['ramps'] })
console.log(features)
}}
...
/>

How to get data from custom component?

I have an edit action inside my model file. I am using default react-admin components, unfortunately I had to created my custom component and after the form is submitted no data from this custom component were provided.
I have tried to wrap the whole component inside <FormControl> , it does not do the trick for me.
My component:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Input from '#material-ui/core/Input';
import InputLabel from '#material-ui/core/InputLabel';
import MenuItem from '#material-ui/core/MenuItem';
import FormControl from '#material-ui/core/FormControl';
import Select from '#material-ui/core/Select';
import Chip from '#material-ui/core/Chip';
import { fetchUtils } from 'react-admin';
const styles = theme => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120,
maxWidth: 300,
},
chips: {
display: 'flex',
flexWrap: 'wrap',
},
chip: {
margin: theme.spacing.unit / 4,
},
noLabel: {
marginTop: theme.spacing.unit * 3,
},
});
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
function getStyles(name, that) {
return {
fontWeight:
that.state.name.indexOf(name) === -1
? that.props.theme.typography.fontWeightRegular
: that.props.theme.typography.fontWeightMedium,
};
}
var names = [];
class MultipleSelect extends React.Component {
state = {
name: [
]
};
getRoles() {
const url = 'URLTOENDPOINT'
var data = [];
fetchUtils.fetchJson(url, {
method: "GET",
})
.then(response => {
Object.keys(response.json.value).forEach(function (key) {
var object = response.json.value[key];
data.push({
name: object.Name,
value: object.Id
});
})
this.setState({name: data});
});
}
getAllOptions() {
const url = 'URLTOENDPOINT'
var data = [];
fetchUtils.fetchJson(url, {
method: "GET",
})
.then(response => {
Object.keys(response.json.value).forEach(function (key) {
var object = response.json.value[key];
data.push({
name: object.Name,
value: object.Id
});
})
names = data;
});
}
componentDidMount() {
this.getRoles();
this.getAllOptions();
this.forceUpdate();
}
handleChange = event => {
console.log("y",event);
this.setState({ name: event.target.value });
};
render() {
const { classes } = this.props;
return (
<div>
<FormControl>
<InputLabel htmlFor="UserRoles">Chip</InputLabel>
<Select
multiple
value={this.state.name}
onChange={this.handleChange}
input={<Input id="UserRoles" />}
renderValue={selected => (
<div className={classes.chips}>
{selected.map(obj => (
<Chip key={obj.value} label={obj.name} className={classes.chip} />
))}
</div>
)}
MenuProps={MenuProps}
>
{names.map(obj => (
<MenuItem key={obj.value} value={obj.value} style={getStyles(obj.name, this)}>
{obj.name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
}
MultipleSelect.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles, { withTheme: true })(MultipleSelect);
EditAction:
export const UserEdit = props => (
<Edit {...props} title={<UserTitle/>} aside={<Aside />}>
<SimpleForm>
<DisabledInput source="Id" />
<TextInput source="Login" validate={required()} />
<TextInput source="Email" type="email" validate={required()} />
<ReferrenceSelectBox source="UserRoles" />
<NullableBooleanInput source="Active" />
<DateField source="CreatedDate" showTime
locales={process.env.REACT_APP_LOCALE}
disabled={true} />
</SimpleForm>
</Edit>
);
I need to show multiple select box with selected data from API, so i had wrote custom component, because default components did not help me, but it didnt change anything and also the data are not showing.

Resources