Skip to content

w10036w/cross-platform-react-starter

Repository files navigation

Cross Platform React Starter

Usage

  • install globally npm i -g graphql-cli graphql-cli-voyager
  • customize the app name in /app.json, eslint in /.eslintrc.js, babel in /.babelrc.js
  • npm i install modules
  • npm run eject prepare for app
  • npm start start app packager
  • npm run ios or npm run android to run app
  • npm run start:web to run web
  • more info check /package.json

Knowledge

Todo

  • client

  • web only

    • client set head Accept-Encoding: gzip
    • polyfill from Financial Time <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
  • app only

React Hooks advanced understanding

// mimick `constructor` or `componentWillMount`
const instance = useRef(null);
useState(() => {
  instance.current = "initial value";
});

// mimick `forceUpdate`
function useForceUpdate() {
  const [_, forceUpdate] = useState(0);
  return () => forceUpdate(x => x + 1); // update a irrelevant state
}

// mimick `componentDidUpdate` or both `componentDidMount` and `componentDidUpdate`
let mount; // define this inside function component
useEffect(() => {
  console.log("did mount and update");
  if (mount) {
    console.log("did update");
  } else {
    mount = true;
  }
}); // don't pass the 2nd argument, meaning always exec

// mimick `componentDidMount`
useEffect(() => {
  if (!mount) {
    mount = true;
    console.log("did mount");
  }
}, []); // no deps, only exec once

// mimick `componentWillUnmount`
useEffect(() => {
  return () => {}; // the return fn is executed at the end of the component
});

// !! Capture Value for useState, useEffect (if 2nd argument is undefined)
// !! Capture Value is not for useRef
const [temp, setTemp] = React.useState(5);
// temp, setTemp are CONST
// they are different in each new render
const log = () => {
  setTimeout(() => {
    console.log("initially temp = 5,now temp =", temp); // still 5!!
  }, 3000);
};

return (
  <div
    onClick={() => {
      log(); // when triggered, temp=5, "captured"
      setTemp(3);
    }}
  >
    click to see log
  </div>
);

// if need to modify props (computed values), consider using `useMemo`
// to cache results until the props change
function Button({ size, color, children }) {
  const textColor = useMemo(
    () => slowlyCalculateTextColor(color),
    [color] // ✅ `textColor` is not recalculated until `color` changes
  );
  return (
    // ✅ `size` is always updated!
    <button className={"Button-" + textColor + "-" + size}>{children}</button>
  );
}

// useEffect is async using requestIdleCallback
// uselayoutEffect is sync

Common Issues

  • chokidar (required by @babel/cli) relies on an old version fsevents, whichi has issues in node v12+; use node v10.15.x as of now.
  • reset react-native cache
    • npm cache clean -f
    • npm i
    • watchman watch-del-all
    • kill watchman daemon process
    • rm -fr $TMPDIR/metro*
  • Error: fsevents unavailable

Archives

Click to view

relay

relay npm script

"relay": "npm run schema && relay-compiler --src ./src --schema ./src/schema.graphql --extensions js jsx --watch"

deps

react-relay relay-runtime relay-compiler babel-plugin-relay eslint-plugin-relay