This is my first time making graphs in React so I'm following the guide and documentation. I have no prior experience with graphology, sigma.js or react-sigma (I know how to use normal React).
The setup documentation says:
Import the React Sigma style file in your application. Example : import "#react-sigma/core/lib/react-sigma.min.css"
What are style files? CSS? How can I make one? I can't find any documentation. Is it something basic from a previous library?
Honestly I'm finding it very hard to learn sigma.js and insert it in my react website. I can't find any guides. Are there any? I just want to start with a simple graph and learn from there.
The documentation refers specifically to their own CSS file which must be imported in a React app like they are showing in the example:
import "#react-sigma/core/lib/react-sigma.min.css";
Disclaimer: depending on your React app setup, the way to import a CSS file might differ.
The example in the documentation was broken when I wrote this answer. I opened an issue on the react-sigma repo and it was fixed since then.
When I tried it, some dependencies were missing and some changes were needed.
npm install #react-sigma/core sigma graphology graphology-types lodash
import { useEffect } from "react";
import Graph from "graphology";
import { SigmaContainer, useLoadGraph } from "#react-sigma/core";
// Import the style file here
import "#react-sigma/core/lib/react-sigma.min.css";
export const LoadGraph = () => {
// first change to their example
const loadGraph = useLoadGraph();
// also wrapped their graph instantiation side-effect with useEffect
useEffect(() => {
const graph = new Graph();
graph.addNode("first", {
// Required position
x: 1,
y: 1,
size: 15,
label: "My first node",
color: "#FA4F40"
});
// Calling the function that was missing from the example
loadGraph(graph);
}, [loadGraph]);
// Returning null to get a valid component
return null;
};
export const DisplayGraph = () => {
return (
<SigmaContainer style={{ height: "500px", width: "500px" }}>
<LoadGraph />
</SigmaContainer>
);
};
Note that I used TypeScript for the example, which gives insightful error messages since react-sigma provides its own types.
Then it was clear that the useLoadGraph hook wasn't used properly since it doesn't accept any parameter and it returns a function accepting a graph parameter. This can be confirmed with the API documentation.
I also figured that lodash was missing from errors in the developer console.
Please refer to the documentation as it's now up-to-date.
Related
I thought react is less pain than Angular for such projects, and you could still mix "plain" javascript into your project. So I have in my react project in index.html this script tags:
I try to integrate this example of AR.js into my react component.
<script src='libs/three/example/vendor/three.js/build/three.js'></script>
<!-- jsartookit -->
<script src="libs/three/vendor/jsartoolkit5/build/artoolkit.min.js"></script>
<script src='libs/three/vendor/jsartoolkit5/js/artoolkit.api.js'></script>
<!-- include threex.artoolkit -->
<script src="libs/three/src/threex/threex-artoolkitsource.js"></script>
<script src="libs/three/src/threex/threex-artoolkitcontext.js"></script>
<script src="libs/three//src/threex/threex-arbasecontrols.js"></script>
<script src="libs/three/src/threex/threex-armarkercontrols.js"></script>
<script>THREEx.ArToolkitContext.baseURL = '../'</script>
Now I want in my ARcomponent.js make use of this THREE and THREEx:
import React, { Component } from 'react'
export class ARcomponent extends Component {
componentDidMount() {
// init renderer
var renderer = new THREE.WebGLRenderer({
antialias : true,
alpha: true
});
//...
}
render() {
return (
<div className="canvas">
</div>
)
}
}
export default ARcomponent
but I get the error message that THREE and THREEx are undefined..
Line 200:20: 'THREE' is not defined no-undef
How can I use Three.js with AR.js (NOT with fiber! not with Aframe!) in my react project? Yes I tried npm install three - but where do I get THREEx and AR.js as npm packages?
Even when I get those errors and my app breaks - when I check on the F12 console THREE and THREEx are loaded.. maybe I need somehow wait a bit longer in my component with using THREE and THREEx?
AR.js in a React environment
AR.js not provide a npm package with ES6 standard yet but there is a PR #116 on the way to add this feature. In the meantime folow this instructions if you want to test:
import AR.js with npm
You need to manually write the import (in package.json) in this way:
"#ar-js-org/ar.js": "https://github.com/AR-js-org/AR.js.git#<GIT_COMMIT_HASH>"
where the <GIT_COMMIT_HASH> is the latest git commit hash (take it from the latest commit in the ES6 branch!)
Example code
I will not post the whole code, but consider that Ar.js is based on Three.js and the preferable way to load it, is in the ComponentDidMount:
import React from 'react'
import { ArToolkitProfile, ArToolkitSource, ArToolkitContext, ArMarkerControls} from 'arjs/three.js/build/ar-threex.js';
import * as THREE from 'three';
export default class ThreexComp extends React.Component {
componentDidMount() {
// your AR.js code here!
}
render() {
return (
<div
style={{ width: "800px", height: "800px" }}
ref={mount => { this.mount = mount}}
/>
)
}
}
You can take a look at this my testing example here: and you can also take in consideration this issue
Final considerations
Importing Ar.js as a npm package, with the ES6 standard, it will be the best way to import into React and similar frameworks. But it is still in devlopment,and could be some bugs. Anyway we think to merge in the dev branch soon and publish a first beta package.
I am using React Markdown (https://www.npmjs.com/package/react-markdown) to render markdown content in my NextJS project.
When I refresh I have two "toto" & "titi" in my terminal... It is normal or what's wrong with this code?
import Head from 'next/head';
import ReactMarkdown from 'react-markdown';
function Section ({ data }) {
const content = JSON.parse(data.markdown);
const {
title,
sortContent
} = data;
console.log('toto');
return (
<>
<main>
<h1>{title}</h1>
<h1>{sortContent}</h1>
<ReactMarkdown source={content.default} escapeHtml={false} />
</main>
</>
)
}
export async function getServerSideProps (context) {
const json = await import('../../content/article1/data.json');
const content = await import('../../content/fr/article1/content.md');
console.log('titi');
return {
props: {
data: {
title: json.title_content,
sortContent: json.short_content,
markdown: JSON.stringify(content)
}
}
}
}
export default Section
It's part of Reacts development tooling, StrictMode. It is expected and only applies in development mode. You can remove the StrictMode to see it only render the expected number of times, but obviously you lose some development tooling. This tooling can warn you about certain unsafe or unwise practices you might want to avoid such as using legacy APIs.
More details here:
Reactjs Docs
A blog with a good overview
If this is truly the only code you have, then it looks like it's normal. You may have other code that uses these components and that's why in shows twice. But based off the code you have right there, there's no bug.
This is a known side-effect of using React.StrictMode, only in debug mode. You can read more about this here.
Strict mode can’t automatically detect side effects for you, but it
can help you spot them by making them a little more deterministic.
This is done by intentionally double-invoking the following functions:
Class component constructor, render, and shouldComponentUpdate methods
Class component static getDerivedStateFromProps method
Function component bodies
State updater functions (the first argument to setState) Functions passed to useState, useMemo, or useReducer
I know this question has been asked multiple times before but none of the solution seems to work.
I'm trying to use the library 'react-chat-popup' which only renders on client side in a SSR app.(built using next.js framework) The normal way to use this library is to call import {Chat} from 'react-chat-popup' and then render it directly as <Chat/>.
The solution I have found for SSR apps is to check if typedef of window !=== 'undefined' in the componentDidMount method before dynamically importing the library as importing the library normally alone would already cause the window is not defined error. So I found the link https://github.com/zeit/next.js/issues/2940 which suggested the following:
Chat = dynamic(import('react-chat-popup').then(m => {
const {Foo} = m;
Foo.__webpackChunkName = m.__webpackChunkName;
return Foo;
}));
However, my foo object becomes null when I do this. When I print out the m object in the callback, i get {"__webpackChunkName":"react_chat_popup_6445a148970fe64a2d707d15c41abb03"} How do I properly import the library and start using the <Chat/> element in this case?
Next js now has its own way of doing dynamic imports with no SSR.
import dynamic from 'next/dynamic'
const DynamicComponentWithNoSSR = dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
Here is the link of their docs: next js
I've managed to resolve this by first declaring a variable at the top:
let Chat = ''
then doing the import this way in componentDidMount:
async componentDidMount(){
let result = await import('react-chat-popup')
Chat = result.Chat
this.setState({
appIsMounted: true
})
}
and finally render it like this:
<NoSSR>
{this.state.appIsMounted? <Chat/> : null}
</NoSSR>
You may not always want to include a module on server-side. For
example, when the module includes a library that only works in the
browser.
Import the library normally in child component and import that component dynamically on parent component.
https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr
This approach worked for me.
I am (very) new to React and have been given the task of adding some data to a component that's being brought in from another file. This file spits out some JSON and I want to access certain pieces of data from it, for example:
config.forms.enquiry.title
I am importing the file fine - no problems there. But I am not sure how to include config into my props.
I found a working example, in another file, and have copied what it does. My code is as such
Brings in file with JSON:
import { withSettings } from 'services/settingsFile';
Add config in render function:
render () {
const styles = getStyles(this.props, this.context, this.state);
const { config } = this.props;
// other stuff
Add to propTypes:
enquiryForm.propTypes = {
config: PropTypes.object.isRequired,
// other stuff
Add to compose:
export const enquiryForm = compose(
withSettings,
// other stuff
However, I get the error:
Failed context type: The context config is marked as required in
n, but its value is undefined.
And from here I am not sure what to do. I know it's a tough question, but I know very little about React and have been thrown in the deep end.
Would anyone know what/where I should be searching for to fix this?
If you can import it like,
import { withSettings } from 'services/settingsFile';
why dont you use it like,
const { config } = withSettings;
OK, so the issue was that there was no wrapping element setting config as am attribute.
I had to go up a level to where my component was being brought in and wrap:
<SettingsFile config={window.settingsFile}>
around:
<Component conf={config} />
Then, the component I was working on was able to read config.
I've only been developing with Meteor 1.4 for a while, and now made the jump to 1.6. Things sure have changed (for the worse).
Meteor used to be so easy to get started with. Now everything is a jumbled mess. It seems like every package wants to insert itself right at the start, so that you can't just import it and use it anymore, you have to change the setup/boilerplate of your app to get it to work. That also means the official documentation is useless because it can't account for every package you want to use.
Anyway, I want to get started with react-router and server-render, which also requires react-helmet (I think). All of these are new to me and hey, they want to insert themselves right away and they all have awful documentation to begin with.
Here's what I have so far, based on googling:
lib/main.js:
import React from 'react'
import { Helmet } from 'react-helmet'
import App from '../imports/ui/App.js'
if (Meteor.isClient) {
import { hydrate } from 'react-dom'
hydrate(<App />, document.getElementById('app'))
}
else {
import { renderToString } from 'react-dom/server'
import { onPageLoad } from 'meteor/server-render'
import NodeCache from 'node-cache'
const renderCache = new NodeCache({stdTTL: 432000})
onPageLoad((sink) => {
const path = sink.request.url.path
let htmlString = renderCache.get(path)
if (!htmlString) {
htmlString = renderToString(<App location={path} />)
const helmet = Helmet.renderStatic()
renderCache.set(path, htmlString)
renderCache.set(path + "_title", helmet.title.toString())
renderCache.set(path + "_meta", helmet.meta.toString())
renderCache.set(path + "_link", helmet.link.toString())
}
sink.appendToHead(renderCache.get(path + "_title"))
sink.appendToHead(renderCache.get(path + "_meta"))
sink.appendToHead(renderCache.get(path + "_link"))
sink.renderIntoElementById("app", htmlString);
})
}
And then App.js is just an empty component right now.
I don't know where to put my routing, or how (the docs assume you already know, for some reason). I think it also needs to insert itself in the hydrate() method on the client, but the example I got it from did not do that so I don't really know.
I don't know whether to put my main.html on the client or both client and server.
I don't know how to set titles and meta tags and whatnot for each route. (I thought this would actually be in the documentation for react-helmet since that's all it's supposed to do but no...)
Can anyone help me with the rest of this boilerplate? I have no idea what's going on in the Meteor world anymore.