We use Reakit dialogs to prompt users to take an action in our React web app.
On some pages, we have specific text related to the action and would like to render this specific content in the dialog. On all other pages, we want to fall back to generic text.
Our simplified component hierarchy for generic pages looks like:
<BaseLayout>
...
</BaseLayout>
and for a page where we want to show specific text,
<BaseLayout>
...
<SpecificPage/>
...
</BaseLayout>
What we'd like to happen is:
On pages that render the SpecificPage component, the Dialog appears with the specific text
On pages that do not render the SpecificPage component, the Dialog appears with the fallback generic text
Our approach was to have the SpecificPage component render a Dialog with the page-specific text, and the BaseLayout component render a Dialog with the generic fallback text, but this approach isn't ideal -- users see a flash of the BaseLayout dialog before the SpecificPage dialog is rendered. Is there any way to define a single component that is "overridden" by descendants in the component hierarchy, or other way to achieve this conditional rendering?
You can simply check if you're rendering anything as children in the BaseLayout component or not, If not you can fallback to generic text.
Here's an example.
App Component
import React from 'react';
import { BaseLayout } from './BaseLayout';
export function App(props) {
return (
<div className='App'>
<BaseLayout>
<h1>Hello World.</h1>
</BaseLayout>. // Renders hello world
<BaseLayout /> // Render generic text
</div>
);
}
Base Layout Component
import React from 'react';
export function BaseLayout({children}) {
return (
<div>
{children ? children : "Some Generic Text"}
</div>
);
}
See https://github.com/ariakit/ariakit/discussions/1266#discussioncomment-2617748 for a solution and CodeSandbox that solves this problem well using the Constate library.
Related
I try getting my React Search box filter to work.
See this sandbox what I have so far.
I have a HOC withSection.js where I add (for now) just a <section> tag to my Components:
const withSection = Component => props => (
<section>
<Component {...props} />
</section>
)
Then in the parent Component I wrap my SearchBox Component into this HOC and render it:
const SectionSearchBox = withSection(SearchBox);
<SectionSearchBox search={search} setSearch={setSearch} />
Somehow, as soon I wrap my SearchBox into this HOC, it breaks the functionality?
Whats wrong here?
You need to declare SectionSearchBox outside the scope of its parent component. In the codesandbox example it would look something like:
import withSection from "./hoc/withSection";
import SearchBox from "./SearchBox";
const SectionSearchBox = withSection(SearchBox);
function ArticlePage() {
...
};
Otherwise every instance of that component is going to be recreated with each new render of its parent (i.e. when the search term changes). This was causing the search box to appear unfocussed with each key stroke, as a new input element was being put in its place with the value from the previous render.
In my react application, when I click on an external link suppose http://www.example.com/about, I do not want it to redirect to that website but I want that about page to render as a popup in my react application. How can I approach this?
You might make a wrapper component for the links that would check if the href prop matches your website location or goes to a 3rd party site, and renders either a normal a tag or a modal dialog with an iframe inside.
Eg. Link.js
import React, { Component, Fragment } from 'react'
import Modal from '...' // any of the available modal component for react
export default class Link extends Component {
state = { isOpen: false }
render () {
const url = new URL(this.props.href)
if (url.hostname === WEBSITE_HOSTNAME) return (
<a href={this.props.href}>{this.props.children}</a>
)
return (
<Fragment>
// you could also use an <a> here if you want users to be able to open the link in a new tab with a right click
<button onClick={() => this.setState({ modalOpen: true })}>{this.props.children}</button>
<Modal isOpen={this.state.isOpen}>
<iframe src={this.props.href} />
</Modal>
</Fragment>
)
}
}
Even better, split it into two components as there's no need for regular links to have any state...
I am trying to create a App using React. I want to add a toast component globally to the app so that it can be referred by other component for displaying custom messages.
I want to add the toast in the following hierarchy:
ReactDOM.render(
<BrowserRouter>
<section>
<App />
<Toast />
</section>
</BrowserRouter>
And refer the Toast Component inside the App. How can I implement it?
you should install package
https://www.npmjs.com/package/react-toastify
and then add import and add
<ToastContainer />
in your header or some component like sidebar which is being used at every page.
You can now show toast messages on any page by just
toast.error("this is toast error");
First you need to import the ToastContainer and the CSS file :
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
and then inside the App.js add the ToastContainer on top :
<React.Fragment>
<ToastContainer />
<NavBar ... />
....
</React.Fragment>
And then you can use the toast popups in any of your components, classes and functions by importing Toast:
import { toast } from "react-toastify";
and then using it with toast() or toast.error() or toast.info() etc methods
toast("Wrong email or Password");
...
toast.error("Some kind of Error");
Hope it helps !
I've tried that approach (including ToastContainer component), but the toast.something didn't fire the event through the Toast component. The solution I've implemented was creating a function that mimics a component behavior, and instead of passing conditionals through props, pass arguments. Here's an example:
import React from "react";
import { toast } from "react-toastify";
const Toast = (message, type) => {
switch (type) {
case "success":
return toast.success(
<div>
<p>{message}</p>
</div>
);
case "error":
return toast.error(
<div>
<p>{message}</p>
</div>
);
case "warning":
return toast.warning(
<div>
<p>{message}</p>
</div>
);
default:
return toast.warning(
<div>
<p>Toast not defined...</p>
</div>
);
}
};
export default Toast;
Somewhere in the component:
Toast('Action successfully executed!', 'success');
You can pass the Toast component to App as a prop.
But this is probably not what you should do. I assume you want the Toast component to be triggered by various things other components can do. You would do this with state. Make Toast a function of state, and let other components modify state. You can do this with plane old setState, or use Redux. Though the author of Redux would tell you to just use setState.
Also because it is React there are already probably 7 libraries for doing this. This one looks promising.
Install toastify package from npm import it to your program and add the following to your program
<ToastContainer/>
You may also be interested in react-toastify so take a look at that.
I have just started learning react and Meteor. I am using the okgrow:accounts-ui-react to show a login and signup form on my site. You only have to add the component to show the signup/login form on your page. However, the dropdown form is ugly and does not go well with my site's design. Therefore, I want to learn how can you modify the styles of such meteor components. In this case, how can you change the style of this component to appear as a materially design form. I am using materialize.css and I want to know how can I give this login component a materialize design inspired look? I want to make the dropdown inspired by material design and also change the contents of the form. The following is my component that I created by following a video on leveluptuts.
import React, {Component} from 'react';
import { LoginButtons } from 'meteor/okgrow:accounts-ui-react';
class App extends Component{
render(){
return (
<div>
<header>
<h1>Level Up Voting </h1>
<LoginButtons/>
</header>
</div>
);
}
}
The following image shows how my login button appears on screen:
I've was testing the react-sketchapp which looks pretty neat so far.
Besides rendering the default sketch elements like Text,View,Image and so on, would it be possible to render a default react component containing HTML-Markup styled with scss?
I tried rendering the following Hello-Component:
import React from 'react';
import { render, Artboard, Text, View } from 'react-sketchapp';
const Hello = () => (
<View
name={`Hello View`}
>
<Text name="Hello Text">
<span>Hello World</span>
</Text>
</View>
);
const Document = () => (
<Artboard
name="Hello Board"
>
<Hello />
</Artboard>
);
export default (context) => {
render(<Document />, context.document.currentPage());
}
but I get the following error:
Could not find renderer for type 'span' flexToSketchJSON
Is rendering default react components including html / css to Sketch possible?
You can't render HTML elements to Sketch, same as you can't render HTML elements to React Native.
React is just a way of managing a tree of abstract components. How to render these components needs to be defined by the specific renderer you are using. react-sketchapp is a renderer that understands components which render to Sketch elements, but it does not understand HTML elements such as div. (and React Native includes a renderer which knows how to render React Native components to native mobile views, react-music is a renderer which knows how to render React Music components into audio, and so forth).
React, in and of itself, has nothing to do with HTML elements or the DOM. The react-dom renderer library is where the magic of rendering into the DOM happens. If you want to render HTML elements to Sketch, you'll need to write a React renderer which knows how to convert HTML elements to Sketch's file format.
You can export any HTML/CSS to Sketch using html-sketchapp.
It is possible.
Try looking into using React-Primitives with React-SketchApp.
https://github.com/lelandrichardson/react-primitives
It's in a few examples within React-SketchApp e.g.
https://github.com/airbnb/react-sketchapp/tree/master/examples/profile-cards-primitives