I try use Notistack in my project but I have a little problem. I installed tthis library and I try use that in the basic version:
import { SnackbarProvider, enqueueSnackbar } from 'notistack'
const App = () => {
return (
<div>
<SnackbarProvider />
<button onClick={() => enqueueSnackbar('That was easy!')}>Show snackbar</button>
</div>
)
}
But it display error:
Uncaught (in promise) SyntaxError: The requested module '/node_modules/.vite/deps/notistack.js?t=1664307735906&v=92d18e2e' does not provide an export named 'enqueueSnackbar'
After I remove importing enqueueSnackbar and onClick from button, app runing but this feature doesn't work, of course. I tryed other option: second code from docs and here I used useSnackbar (I know this code is different but I show only this frament which generate the error):
const { enqueueSnackbar, closeSnackbar } = useSnackbar()
Effect is very similar - enqueueSnackbar is undefined. How can I use this library? I don't know that this is important but I use Laravel + Breeze + #mui.
You need to wrap all parent component to SnackbarProvider component.
import { SnackbarProvider, enqueueSnackbar } from 'notistack'
const App = () => {
return (
<SnackbarProvider>
<div>
<button onClick={() => enqueueSnackbar('That was easy!')}>Show snackbar</button>
</div>
</SnackbarProvider>
)
}
Related
I am working on the following project https://github.com/codyc4321/react-udemy-course section 11 the videos app. The udemy course is found at https://www.udemy.com/course/react-redux/learn/lecture/12531374#overview.
The instructor is passing a callback down to multiple children and calling it in the lowest videoItem and the code is supposed to console log something out. I have no console log in my browser even though I've copied the code as written and double checked for spelling errors.
At the main level is App.js:
import React from 'react';
import youtube from '../apis/youtube';
import SearchBar from './SearchBar';
import VideoList from './VideoList';
class App extends React.Component {
state = {videos: [], selectedVideo: null};
onTermSubmit = async term => {
const response = await youtube.get('/search', {
params: {
q: term
}
});
// console.log(response.data.items);
this.setState({videos: response.data.items});
};
onVideoSelect = video => {
console.log('from the app', video);
}
render() {
return (
<div className="ui container">
<SearchBar onFormSubmit={this.onTermSubmit} />
<VideoList
onVideoSelect={this.onVideoSelect}
videos={this.state.videos} />
</div>
)
}
}
export default App;
videoList.js
import React from 'react';
import VideoItem from './VideoItem';
const VideoList = ({videos, onVideoSelect}) => {
const rendered_list = videos.map(video => {
return <VideoItem onVideoSelect={onVideoSelect} video={video} />
});
return <div className="ui relaxed divided list">{rendered_list}</div>;
};
export default VideoList;
the videoItem.js
import React from 'react';
import './VideoItem.css';
const VideoItem = ({video, onVideoSelect}) => {
return (
<div onClick={() => onVideoSelect(video)} className="item video-item">
<img
src={video.snippet.thumbnails.medium.url}
className="ui image"
/>
<div className="content">
<div className="header">{video.snippet.title}</div>
</div>
</div>
);
}
export default VideoItem;
The code that isn't running is
onVideoSelect = video => {
console.log('from the app', video);
}
My guess is that it has something to do with a key prop not being present in the map - I'm not super well versed with class components but I can't find anything else funky so maybe try adding a unique key prop in the map.
When rendering components through a map react needs help with assigning unique identifiers to keep track of re-renders etc for performance, that also applies to knowing which specific instance called a class method.
If you don't have a unique ID in the video prop you can use an index in a pinch, although ill advised, it can be found as the second parameter in the map function. The reason it's ill advised to use an index is if there are multiple children with the same index in the same rendering context, obviously the key parameter could be confused.
Okay-ish:
const rendered_list = videos.map((video, index) => {
return <VideoItem key={index} onVideoSelect={onVideoSelect} video={video} />});
Better:
const rendered_list = videos.map((video, index) => {
return <VideoItem key={video.id} onVideoSelect={onVideoSelect} video={video} />});
I saw many examples it works fine for all but I don't know why it does not highlight my code.
I tried many solutions none of them work for me.
Also, I need to inject my own custom HTML file in it for the initial when user click on demo for the code and also user can change the file and run its own custom code that user want.
Here is the screenshot of the output:
Code that I used for the editor
import React from 'react';
import {Controlled as ControlledEditor} from 'react-codemirror2';
import {language} from "#hapi/accept";
import {codecs} from "next/dist/next-server/server/lib/squoosh/codecs";
if (typeof navigator !== 'undefined') {
require('codemirror/mode/xml/xml');
require('codemirror/mode/css/css');
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/markdown/markdown');
}
const Editor = (props) => {
const {
displayName,
value,
onChange
} = props
const handleChange = (editor,date,value) => {
onChange(value);
}
return (
<div className="editor-container">
<div className="editor_title">
{displayName}
<button>O/C</button>
</div>
<ControlledEditor
onBeforeChange={handleChange}
value={value}
className={'code-mirror-wrapper'}
options={{
lineWrapping:true,
lint:true,
mode:language,
theme:'dracula',
lineNumbers:true
}}
/>
</div>
)
}
export default Editor;
That is the new file where I call my editor:
import React,{useState,useEffect} from 'react';
import Editor from '../../component/Editor/editor';
const RunCode = () => {
const [html,setHtml] = useState();
const [css,setCss] = useState();
const [JS,setJS] = useState();
const [scrDoc,setSrcDoc] = useState('');
useEffect(()=>{
const timeout = setTimeout(()=>{
setSrcDoc(
`<html>
<body>${html}</body>
<style>${css}</style>
<script>${JS}</script>
</html>`
)
},250)
return () => clearTimeout(timeout)
},[html,JS,css]);
return(
<>
<div className={'pane top-pane'}>
<Editor
language={'xml'}
displayName={'HTML'}
value={html}
onChange={setHtml}
/>
<Editor
language={'CSS'}
displayName={'CSS'}
value={css}
onChange={setCss}
/>
<Editor
language={'JS'}
displayName={'JS'}
value={JS}
onChange={setJS}
/>
</div>
<div className="output">
<iframe
srcDoc={scrDoc}
title={'Output'}
sandbox={'allow-scripts'}
height={'100%'}
width={'100%'}
>
</iframe>
</div>
</>
)
}
export default RunCode;
The short answer is: You might not be importing the .css file to use the "Dracula" theme.
Make sure you are importing these two files from node_modules in the component in which you are using ControlledEditor, to provide the theme to your editor.
import "codemirror/lib/codemirror.css";
import "codemirror/theme/dracula.css";
PS: My personal favorite theme is: ayu-dark ;)
I have also made a similar thing. Here is a Github Repo for your reference. :)
FunFact: #juliomalves helped me in deploying this project on vercel.😁
Problem
Using React-Markdown I can fully use my custom built components. But this is with specific pre-built keywords in the markdown. Like paragraph or images. That works PERFECTLY. But the problem is that these seem to all be pre-built words/conditions like paragraphs, headers, or images.
I can't find a way to add something new key word in my markdown like "CustomComponent" to be used. That's all I need at this point ><
This works just fine for me to make the markdown's image into a custom "footer" component I made elsewhere. I know it's ridiculous but it works. But I have no idea how to make this renderer accept/create a new keyword like "emoji" or "customComponent" or "somethingSilly".
let body =
`![Fullstack React](https://dzxbosgk90qga.cloudfront.net/fit-in/504x658/n/20190131015240478_fullstack-react-cover-medium%402x.png)`;
const renderers = {
image: () => <Footer/>
};
<ReactMarkdown source={body} renderers={renderers} />;
Some past work I did:
Some documentation:
https://reposhub.com/react/miscellaneous/rexxars-react-markdown.html
https://github.com/rexxars/commonmark-react-renderer/blob/master/src/commonmark-react-renderer.js#L50
Examples:
https://codesandbox.io/s/react-markdown-with-custom-renderers-961l3?from-embed=&file=/src/App.js
But nothing indicates how I can use "CustomComponent" to indicate to inject a custom component.
Use Case / Background
I'm trying to retrieve an article from my database that is formatted like so in markdown (basically a giant string). I'm using regular react with typescript and redux-- this is the only portion of my application that needs this.
"
# Title
## Here is a subtitle
Some text
<CustomComponentIMade/>
Even more text after.
<CustomComponentIMade/>
"
I know its most likely a little late for your purposes, but I've managed to solve this issue using a custom remark component.
Essentially you'll need to use the remark-directive plugin as well as a small custom remark plugin (I got this plugin straight from the remark-directive docs)
Then in react markdown you can specify the plugins, custom renderers and custom tags for eg.
import React from 'react'
import ReactMarkdown from 'react-markdown'
import {render} from 'react-dom'
import directive from 'remark-directive'
import { MyCustomComponent } from './MyCustomComponent'
import { visit } from "unist-util-visit"
import { h } from "hastscript/html.js"
// react markdown components list
const components = {
image: () => <Footer/>,
myTag: MyCustomComponent
}
// remark plugin to add a custom tag to the AST
function htmlDirectives() {
return transform
function transform(tree) {
visit(tree, ['textDirective', 'leafDirective', 'containerDirective'], ondirective)
}
function ondirective(node) {
var data = node.data || (node.data = {})
var hast = h(node.name, node.attributes)
data.hName = hast.tagname
data.hProperties = hast.properties
}
}
render(
<ReactMarkdown components={components} remarkPlugins={[directive, htmlDirectives]}>
Some markdown with a :myTag[custom directive]{title="My custom tag"}
</ReactMarkdown>,
document.body
)
So in your markdown wherever you have something like :myTag[...]{...attributes} you should render the MyCustomComponent with attributes as props.
Sorry I haven't tested the code, but hopefully it communicates the gist of things, if you need a working example let me know and I'll do my best to set one up.
I have tried this way and it worked for me
import CustomNextImage from '#commonComponentsDependent/CustomNextImage';
import dynamic from 'next/dynamic';
import Link from 'next/link';
import { FC } from 'react';
import ReactMarkdown from 'react-markdown';
import { Options } from 'react-markdown/lib/ast-to-react';
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
import remarkGfm from 'remark-gfm';
const SyntaxHighlighterDynamic = dynamic(() => import('./SyntaxHighlighter'));
import classes from './styles.module.css';
interface Props {
content: string;
}
type TCustomComponents = Options['components'];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const MdToHTML: FC<Props> = ({ content }) => {
const customComponents: TCustomComponents = {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
img(image) {
if (!image.src) return <></>;
return (
<div className={classes['img-container']}>
<CustomNextImage
src={image.src}
alt={image.alt}
/>
</div>
);
},
a({ href, children, node }) {
if (!href) return <></>;
if (
href.startsWith('/') ||
href.startsWith('https://lognmaze.com')
) {
return (
<Link href={href} prefetch={false} passHref>
<a>{children}</a>
</Link>
);
}
return (
<a
href={href}
target='_blank'
rel='noopener noreferrer'
>
{children}
</a>
);
},
code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<SyntaxHighlighterDynamic language={match[1]} PreTag='div' {...props}>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighterDynamic>
) : (
<code className={className} {...props} data-code-inline='true'>
{children}
</code>
);
},
};
return (
<ReactMarkdown
components={customComponents}
remarkPlugins={[remarkGfm]}
>
{content}
</ReactMarkdown>
);
};
export default MdToHTML;
This is surely really easy but I didn't find the solution.. I want to use the delete button but I'm getting an error. Thanks in advance guys.
This is the code where props call the properties of a Toy class parent, I want to delete by Id using MongoDB:
import React, { useContext } from 'react';
import UserContext from '../../context/UserContext';
import Axios from 'axios';
export default function AdminOptions(props) {
const { userData } = useContext(UserContext);
console.log(props.value._id)
//I tried this log and it gives me the id of the toy
deleteToy = async(id) => {
await Axios.delete('api/toys/delete' + id);
alert('Toy deleted');
}
return (
<div>
{userData.user ? (
<>
<br/>
<button className="btn btn-danger" onClick={this.deleteToy(props.value._id)}>
Delete toy
</button>
</>
) : (
<>
</>
)}
</div>
)
}
And this is the error I get
Failed to compile.
Line 15:5: 'deleteToy' is not defined no-undef
You are using the variable deleteToy without defining it (with either const, let or var), hence the error.
You are referring to this.deleteToy, yet your variable is just deleteToy.
In your event handler, you are not passing a function reference but actually calling the function right away. You can prepend () => to fix it (passing an arrow function that then calls yours when called). (Thanks, Emre Koc, I missed that.)
The fixed code would look like this:
import React, { useContext } from 'react';
import UserContext from '../../context/UserContext';
import Axios from 'axios';
export default function AdminOptions(props) {
const { userData } = useContext(UserContext);
console.log(props.value._id)
//I tried this log and it gives me the id of the toy
const deleteToy = async(id) => {
await Axios.delete('api/toys/delete' + id);
alert('Toy deleted');
}
return (
<div>
{userData.user ? (
<>
<br/>
<button className="btn btn-danger" onClick={() => deleteToy(props.value._id)}>
Delete toy
</button>
</>
) : null}
</div>
)
}
Add const before deleteToy . It will work
Sorry, I'm kinda new to react ,why I'm not being able to map through the data.
I have tried a different couple of things but nothing has helped.
Maybe the reason is that it's an object.
Can any one help?
import React, { Component } from "react";
import axios from "axios";
import "./Profile.css";
import ProfileCard from "../ProfileCard/ProfileCard";
class Profile extends Component {
state = {
userInfo: {}
};
componentDidMount() {
const { id } = this.props.match.params;
axios
.get(`/api/user/info/${id}`)
.then(
response => this.setState({ userInfo: { ...response.data, id } }),
() => console.log(this.state.userInfo)
);
}
render() {
let userInfoList= this.state.userInfo.map((elem,i)=>{
return(
<div> name={elem.name}
id={elem.id}</div>
)
})
console.log(this.state.userInfo);
return (
<div>
{/* <p>{this.state.userInfo}</p> */}
{/* <div >{userInfoList}</div>
<ProfileCard profilePic={this.state.userInfo} /> */}
</div>
);
}
}
export default Profile;
I think I understand what youre trying to do.
First you should change userInfo to an empty array instead of an empty object as others have stated.
Next since you are making an async api call you should use a ternary expression in your render method, because currently React will just render the empty object without waiting for the api call to complete. I would get rid of the userInfoList variable and refactor your code to the following:
RenderProfile = (props) => (
<div>
{props.elem.name}
</div>
)
{ this.state.userInfo
? this.state.userInfo.map(elem => < this.RenderProfile id={elem.id} elem={elem} /> )
: null
}
Let me know if it worked for you.