How to implement MobX in Create-React-App? - reactjs

While studying React, and Redux, I was told to have a look at MobX as well, because it's much simpler. And I agree, I find it more intuitive when demonstrated to me.
But when I try to implement it in my React project I run into a lot of trouble, e.g. with the decorators, experimental syntax warnings and when fixed I run into a lot of more trouble.
And I can't follow tutorials, it does not look the same to me when I try it, new versions have arrived since then, etc..
After installing:
npm install mobx --save
npm install mobx-react --save
...what confuses me is the usage of the 2 files for further settings (or do I need just one of them?):
.babelrc
babel.config.js
Do I have to create those files myself (or just one of them)?, and WHERE??
And I am also told by tutorials to change babel section in package.json, but there is no such section.
Right now I am stuck in a compiler (VSCode) error:
"Support for the experimental syntax ‘decorators-legacy’ isn’t currently enabled".
I did run the command:
npm install #babel/plugin-proposal-decorators
.. but there is still that error when compiling in VSCode.

In MobX 6 there is a new thing that will probably allow you to drop decorators altogether, makeAutoObservable:
import { makeAutoObservable } from "mobx"
class Store {
// Don't need decorators now
string = 'Test String';
setString = (string) => {
this.string = string;
};
constructor() {
// Just call it here
makeAutoObservable (this);
}
}
With that you don't even need decorator syntax to be enabled.
More info here
https://mobx.js.org/migrating-from-4-or-5.html
and
https://mobx.js.org/react-integration.html

Related

Using ES6 import module aliases with create-react-app

In Angular, it's pretty straightforward to rewrite your imports, so that something like this:
import { ProgressBar } from '../../common';
becomes this:
import { ProgressBar } from '#common';
Is this possible in react nowadays with create-react-app? I have done a lot of reading, and it seems I have one of these options:
eject my app and fiddle with the config directly; or
install cracro or some other create-react-app hack
Is there a third? Since I very strongly don't want to do either of these?
Bonus points: will my JetBrains IDE understand these module aliases when refactoring/optimising imports?

requestAnimationFrame is not defined it Next.js with React Native Web (Animated module)

I'm working on Next.js and React-Native-Web. I managed to run them together following the official Next.js example but when I'm trying to use the Animated package from the react-native it fails with Error that the requestAnimationFrame isn't defined. Basically this functionality does the node_modules package but I set the alias in webpack to translate all react-native requires to the react-native-web so even the node_modules package should use the react-native-web.
Any suggestions on how to solve it?
ReferenceError: requestAnimationFrame is not defined
at start (...node_modules\react-native-web\
dist\cjs\vendor\react-native\Animated\animations\TimingAnimation.js:104:11)
enter code here
Thanks for any help!
The problem is in the missed RequestAnimationFrame functionality at the server. This error happens when Next.js tries to render the component during SSR.
Unfortunately, there is no polyfill, etc. for such purpose so I just decided to use the Next.js dynamic imports for a Component that has animation functionality.
Next.js Official documentation
My own case оust to show how code looks:
import dynamic from 'next/dynamic';
const AutocompleteDropdown = dynamic(
() => import(
'myAwesomeLib/components/dropdown/autocomplete/AutocompleteDropdown'
),
{
ssr: false,
}
);
Now you can use the AutocompleteDropdown as the standard JSX component
I'm coding an App with React Native Web and NextJS 12, and in 2021 I encounter this problem and I fixed it, but now I know my fix was only for Next Dev, because it returned for Next Production Build.
Solution details:
No Dynamic import (which is useful too, but can be annoying when having lot of components using it)
Using RAF polyfill and Webpack ProvidePlugin.
Main thing to have in mind is that next.config.js with webpack 5 is going to check the codes first before even reach next entry points _documents.js and _app.js. It means that, you can put polyfill in those entry point files, it will still raise error of RAF undefined. You have to make requestAnimationFrame ready for config check.
DEV approach that will work on Next DEV only. Install RAF package https://www.npmjs.com/package/raf and In next.config.js add codes:
const raf = require('raf');
raf.polyfill();
This will add requestAnimationFrame and cancelAnimationFrame function to global and window object if they don't have it. In our case, it would add it in global for NodeJS.
But this solution won't work when executing npm run dev. I don't know why, if anyone knows why Next or Webpack 5 act differently from DEV to PRODUCTION, let me know.
Complete Solution:
Use ProvidePlugin config of webpack 5 https://webpack.js.org/plugins/provide-plugin/ . Create a file to use as modules, let's say: raf.js in root project or anywhere you want:
const raf = require('raf');
const polys = {};
raf.polyfill(polys);
module.exports = polys.requestAnimationFrame;
And in next.config.js use it inside webpack: () = {} like:
webpack: (config, options) => {
// console.log('fallback', config.resolve.fallback);
if (options.isServer) {
// provide plugin
config.plugins.push(
new options.webpack.ProvidePlugin({
requestAnimationFrame: path.resolve(__dirname, './raf.js'),
}),
);
}
And now, it's up to you to adapt to your existing config logic. By doing this, in Production Build, NextJS is injecting the requestAnimationFrame function in Server Side everywhere a module is using it.

How to use Sigma.js in React with Typescript

I'm trying to set up a simple web app with React/TypeScript so I can fiddle with some graphs with Sigma.js. But I can't get the end result to render anything with Sigma.
Here's the steps I followed:
$ npx create-react-app sigmafiddle --template typescript^C
$ cd sigmafiddle
$ yarn add sigma
$ yarn add #types/sigmajs
However, when I go to import Sigma I encounter the following problems:
import { sigma } from 'sigma'
Fails with this error message:
TypeScript error in ~/devel/sigmafiddle/src/App.tsx(4,23):
Could not find a declaration file for module 'sigma'. '~/devel/sigmafiddle/node_modules/sigma/endpoint.js' implicitly has an 'any' type.
Try npm install #types/sigma if it exists or add a new declaration (.d.ts) file containing declare module 'sigma'; TS7016
Not a real helpful message, since #types/sigma does not exist within npm.
And if I try this:
import { sigma } from 'sigmajs'
I get this failure:
TypeScript error in ~/devel/sigmafiddle/src/App.tsx(4,23):
File '~/devel/sigmafiddle/node_modules/#types/sigmajs/index.d.ts' is not a module. TS2306
I've also tried the package react-sigma:
yarn add react-sigma
// in app.tsx
import {Sigma, RandomizeNodePositions, RelativeSize} from 'react-sigma';
Unfortunately there is no #types/react-sigma package, so this results in the following error:
Cannot find module 'react-sigma'
How can I get sigma.js to work with TypeScript and React?
You didn't import what you are trying to use
replace
/// <reference types="#types/sigmajs" />
to
import { sigma } from 'sigma';
Usually, import as above is the common way to use lib in js/ts project.
Update
Since the error seems to be lacking type definition of the lib,
File '~/devel/graph-grammar/node_modules/#types/sigmajs/index.d.ts' is not a module.
npm install --save #types/sigmajs
And import as normal may work.
import { sigma } from 'sigma';
Refer to #types/sigmajs
Update No.2
You may need react-sigma npm, repo in your react project instead.
Install it, and import refer to the document seems fine.
import {Sigma, RandomizeNodePositions, RelativeSize} from 'react-sigma';
If that not work, try to install both sigma and react-sigma, since ploty.js need both ploty.js and react-ploty.js been installed, I guess you may meet the similar situation.
Update No.3
Seems react-sigma don't support typescript, they support flow-type instead.
Refer: document of react-sigma

Using React-Recaptcha library without NPM

I'm brand new to React and trying to figure out how to use Ract-Recaptcha library (https://github.com/appleboy/react-recaptcha) without NPM.
here is the source code for the Recaptcha wrapper : index.js
Looks like the library imports import PropTypes from 'prop-types';
and in my env NPM is disabled, so I'm wrecking my head ( with very limited React knowledge) trying to understand how to do without PropTypes.
Very much appreciate any help !!
Clone the package into a lib directory or private_modules and import it manually and let Webpack (or whatever module bundler you use) resolve the dependency like code you've written.
In your package.json you can do something like:
{
"name": "MyApp",
"dependencies": {
"myLocalModule": "file:./lib/myLocalModule/dist/index.js"
}
}
Remember, this is our virtual world. There is always a way or at worst a hack! Cheers
https://docs.npmjs.com/files/package.json#local-paths

Requiring unknown module "crypto" in react-native environment

I'm writing a simple Twitter app using react-native. Using twit module to get twitter feeds and stream. Below is the code, it works fine node. However, when included into my react-native app, seeing error "Requiring unknown module "crypto"". Dependency seems to be myapp->twit->oauth->crypto (thats part of node v0.12.2). Any suggestions to get this working inside react-native environment?
var Twit = require('twit')
var T = new Twit({
consumer_key:''
, consumer_secret:''
, access_token:''
, access_token_secret:''
})
var filtered_tweets=[];
var error;
var isSuccess=false;
function getTweets(searchString){
T.get('search/tweets',{q:searchString, count:100}, getResponse);
}
function getResponse(err,data,response){
if(err) {
handleGetErr(err);
}
handleGetData(data.statuses);
}
function handleGetErr(err){
enter code here
error = err;
}
function handleGetData(data){
data.map(function(tweet){
var twit={
twit:tweet.id,
created_at:tweet.created_at,
text:tweet.text,
retweet_count:tweet.retweet_count,
favorite_count:tweet.favorite_count
};
filtered_tweets.push(twit);
});
console.log(filtered_tweets);
isSuccess=true;
}
getTweets("#sahaswaranamam");
module.exports = getTweets;
![attached][2]
The crypto module is a built-in Node module; React Native runs JS on JavaScriptCore (when on the device or simulator) and on Chrome itself (when using Chrome debugging), so modules that depend on built-in Node.js modules won't work. See the JavaScript Runtime section of the React Native docs for more info.
I'm not sure how hard it would be to integrate into a React Native app, but browser module bundlers like Browserify often have browser versions of core Node.js modules, like this one for crypto.
If you are using rn-nodeify as #emmby suggests, then you can use react-native-crypto. Instructions from the README:
Install
npm i --save react-native-crypto
# install peer deps
npm i --save react-native-randombytes
react-native link react-native-randombytes
# install latest rn-nodeify
npm i --save-dev mvayngrib/rn-nodeify
# install node core shims and recursively hack package.json files
# in ./node_modules to add/update the "browser"/"react-native"
# field with relevant mappings
./node_modules/.bin/rn-nodeify --hack --install
rn-nodeify will create a shim.js in the project root directory
// index.ios.js or index.android.js
// make sure you use `import` and not require!
import './shim.js'
// ...the rest of your code
But rn-nodeify also states:
If you're looking for a saner approach, check out ReactNativify. I haven't tested it myself, but I think philikon will be happy to help
With ReactNativify you create a rn-cli.config.js and then in a transformer.js you let Babel transform bundle dependencies using babel-plugin-rewrite-require:
// The following plugin will rewrite imports. Reimplementations of node
// libraries such as `assert`, `buffer`, etc. will be picked up
// automatically by the React Native packager. All other built-in node
// libraries get rewritten to their browserify counterpart.
[require('babel-plugin-rewrite-require'), {
aliases: {
crypto: 'crypto-browserify',
// ...
},
throwForNonStringLiteral: true,
}]
(Note: You can also do this in without these 2 js files directly in .babelrc)
(Note2: Though ReactNativify is the cleaner way, it is still giving me issues wiring up crypto.getRandomValues for production-use in RN. See this question)
You can use the rn-nodeify module to get crypto on react-native.
Add rn-nodeify to your devDependencies in package.json:
"devDependencies": {
"rn-nodeify": "^6.0.1"
}
Add the following to the scripts section of the same file:
"scripts": {
…
"postinstall": "node_modules/.bin/rn-nodeify --install crypto --hack"
}
Be aware that rn-nodeify will modify your package.json.
More information available here: https://www.npmjs.com/package/rn-nodeify
React Native packager uses Babel under the hood. This means that you can use babel-plugin-rewrite-require Babel plugin to rewrite all require('crypto') calls to require('crypto-browserify'), assuming that the latter is installed in your node_modules.
As of January 2016, you can use .babelrc file to define optional configuration, so this becomes really easy. First, install the dependencies:
npm install --save crypto-browserify
npm install --save-dev babel-plugin-rewrite-require
Then add plugins config to your .babelrc file:
{
"presets": ["react-native"],
"plugins": [
["babel-plugin-rewrite-require", {
"aliases": {
"crypto": "crypto-browserify"
}
}]
]
}
Restart the packager and that should be it.
This is the same approach that ReactNativify uses, except that here we use .babelrc instead of defining custom transformer. When ReactNativify was written, it was not supported, so they had to go with more complex solution. See this file from ReactNativify for almost complete list of node polyfills.
I was having the same issue when implementing the Twilio package in my React Native app, and having React Native break over the crypto dependency.
As a work around I ended up creating a separate, stand alone Node/Express app to act as my server and take care of the Twilio logic I had. That way I removed all Twilio logic from my React Native app and moved it to Node. I then just called my Express route in React Native using fetch, which triggered the functionality I wanted to happen with Twilio. If you're unfamiliar with fetch here's a good starting point -
Making AJAX calls with Fetch in React Native
In addition, here's my question on the crypto dependency breaking my app:
twilio-react-native-unable-to-resolve-module-crypto
As far I can see amazon-cognito-identity-js uses crypto-js 3.3.0 without any additional magic... If that version of the package works then perhaps try that.
After having tried a bunch of these solutions and never really having been satisfied with any of them (some didn't even work), I managed to stumble upon react-native-quick-crypto, which honestly worked much more effortlessly than trying to lift the existing crypto library to the front-end

Resources