How to make Ionic React implementation respect UI = f(state)? - reactjs

Ionic React seems not respecting UI = f(state).
I started an application with
ionic start ionic-tests tabs --type react
import IonCheckbox from #ionic/react and used with <IonCheckbox checked />, the expected behavior while clicking is keep checked, but the checkbox was toggling...
Is it the Ionic purpose? There is any way to ensure Ionic React UI as state function?
Ionic uses stencil (web-components) and a layer (called output targets) to solve some connection problems with React. By investigating the code I saw about the #Prop decorator with the mutability option, but it seems doesn't work (so what is the point about the mutability option?).

manage state
const [checked, setChecked] = useState<boolean>(true);
render
<IonCheckbox
checked={checked}
onIonChange={(e: any) => setChecked(e.detail.checked)}
></IonCheckbox>
https://ionicframework.com/docs/api/checkbox

Related

How to access a useState globally?

I am developing a ecommerce site and I have a feature to show cart Items number in nav bar. This nav bar is common for all page so it is in a different file. In the navbar I made the carticon into a react hook and used usestate to get and show cart number.
const CartNumber = () =>{
const [cartNumber, setCartNumber] = React.useState(0);
async function getCartN(){
var d = await getCartItem();
setCartNumber(d.cartData.length);
}
useEffect(()=>{
getCartN();
}, cartNumber);
return <NavLink to="/cart">
<MdOutlineShoppingCart className="cart-icon cart-icons" />
<span id="cart-count">{cartNumber}</span>
</NavLink>
}
Here if I use setCartNumber then the cart number would also update. But the problem is I want to call this outside this file since add to cart button is on another page. So how can I make this setCartNumber globally accesible.
You sould use a context api: https://reactjs.org/docs/context.html
Or a library like redux, to be able to manage the global state of your app: https://redux.js.org/
To achieve this goal, you have to use Redux or Context API.
By using one of them, you can use states globally and update them easily.
In React two states one is local and the second is global.
In Redux state management library handle both states. I highly recommended you should learn the Functional Programming concept and the second thing you learn is redux.
I already face this problem so Mosh instructor resolves my problem and clear the whole concept of redux.
I highly recommend you should see the Mosh redux series.
Context API is not preferred especially in big projects.

What is the best way to have a React-generated static (SEO) "public" frontend alongside a CRA "private" app?

I've been using Create-React-App and dig the whole setup, basically I'm looking to keep developing with JSX instead of switching to Gatsby/React-Static's Markdown/etc coding style. Similar question to this one regarding Gatsby. I'm looking to have a search engine optimized static "public" frontend (e.g. product pages, blog, etc.) that is generated by Gatsby or react-static. But I'd also like a typical client-side rendered React app for the "private" section (e.g. sellers can edit their product pages). I know you can set the "homepage" so I was thinking of setting the private section to "example.com/in/" or similar.
Any advice on how to best split this project?
If you aren't using the GraphQL stuff, Gatsby is predominantly just using React SSR and a custom webpack configuration with Reach Router and some glue to stick it all together.
You can absolutely have a separate Webpack configuration that outputs to your public folder and set up your host/deployment to route all of your non-static routes to your application entry.
You can also use Gatsby to generate all of those dynamic pages with juicy client-side fetches, and you basically get free static skeleton entry points for each of your pages like this:
const useMounted = () => {
const [isMounted, setIsMounted] = useState(false)
useEffect(() => {
setIsMounted(true)
}, [])
return isMounted
}
const SomeComponent = props => {
const isMounted = useMounted()
return isMounted
? <div>Mounted client-side component</div>
: <SomeComponentSkeleton />
}
Effectively this just prevents issues with hydration that occur if you return null on server-side render and then return a component on the client-side. You can also use isMounted to kick off any code that uses window et al.

How to perform a server side data fetching with React Hooks

We just start moving into React Hooks from the React life-cycle and one of the things that we noticed, is that there's no straightforward way to run something similar to ComponentWillMount for loading data before sending the rendered page to the user (since useEffect is not running on SSR).
Is there any easy way supported by React to do so?
I had the same problem. I've managed to solve it with a custom hook and by rendering application twice on the server-side. The whole process looks like this:
during the first render, collect all effects to the global context,
after first render wait for all effects to resolve,
render the application for the second time with all data.
I wrote an article with examples describing this approach.
This is a direct link to the example form article on CodeSandbox.
Also, I have published an NPM package that simplifies this process - useSSE on GitHub.
This is a little tricky but one way around is to do the fetch directly in the component as in
function LifeCycle(props){
console.log("perform the fetch here as in componentwillmount")
const [number, setNumber] = useState(0)
useEffect(() => {
console.log("componentDidMount");
return () => {
console.log("componentDidUnmount");
};
}, []);
}

Switching Layouts Based on Screen Size in Gatsby

I am building a web app using Gatsby that needs to load a separate layout built using mobile ui library in mobile browser and different layout with another ui library when opening in desktop browser.
How should I achieve this at the root (app) component level?
Thank you
I think you can experiment with wrapPageElement in gatsby-browser.js and gatsby-ssr.js, returning different layout based on browser height:
const React = require("react")
const Layout = ...
const MobileLayout = ...
exports.wrapPageElement = ({ element, props }) => {
// a made up hook to detect browser size, implement your own
const isMobile = useDetectMobile()
return (
isMobile
? <MobileLayout {...props}>{element}</MobileLayout>
: <Layout {...props}>{element}</Layout>
)
}
This get tricky though, because during server-side generation you'd need a default layout, which may (or may not?) lead to faulty behavior? I'm not sure.
A safe bet is to generate a mobile version & a desktop version for your app, then detect browser size / type in gatsby-browser & redirect accordingly.

I don't know how to organize a web app that uses component based web framework

I am trying to learn component based frameworks for frontend apps. Currently, I am using RiotJS but it applies to any framework that uses the same concepts (React, Angular 2.0 etc).
In a basic MVC frontend frameworks (e.g AngularJS), the controllers and router were very connected to each other. But with a component based framework, the line between router and controllers is much wider. And this is what confuses me the most.
Here is one example of an app that I am trying to build:
I have three main UI elements: Navigation Bar, Content Area, and Signin Form. So, I created three components: my-navbar, my-content, my-signin. I was able to create multiple routes per component. So for example, if there is a route changes, the navbar updates the active "module." Making this was easy because all I am doing is changing class of a list item.
Now, I want to load other tags inside <my-content></my-content>. In AngularJS, I was always changing the view completely (using ui-router). How can I achieve that in a component based framework. Let's say that I have 2 more components called my-content-users-list-view, my-content-users-detail-view. How can I add them to the component my-content based on the route? Do I just add it like document.innerHTML += '<my-content-users-list-view></my-content-users-list-view>?
I know most of my syntax is RiotJS but I will understand it if you write it in another framework's syntax.
Thank you!
Essentially, yes, you could just append your tag as a DOM node and then call Riot to mount it:
riot.route('/awesome-route', () => {
const tag = 'your-awesome-tag';
const options = { ... };
const elem = document.createElement(tag);
// TODO empty your content container using pure DOM or jQuery to get rid of the previous route's view...
document.querySelector('#content').appendChild(elem);
riot.mount(elem, tag, options);
});

Resources