I have the react-bnb-gallery package with single default exported component named ReactBnbGallery. It shows the gallery through the portal and works well but my goal is to get that gallery inline in html and nested in components tree.
Currently what I have:
<SomeWrapperComponent>
<ReactBnbGallery /> // contains not accessible <Gallery/>
<SomeWrapperComponent />
and I want this:
<SomeWrapperComponent>
<Gallery/>
<SomeWrapperComponent />
In this way I want to omit the portal and have the gallery right inside my layout.
Any suggestions???
I thought about some HOC over the <ReactBnbGallery>
or maybe Portals have some api or another switcher to simply turning off
Thanx in advance !
The Gallery component is now accessible outside the portal.
This is now possible using the following code:
import { Gallery } from 'react-bnb-gallery';
const MyComponent = () => (
<Gallery photos={[...]} />
);
If you want to use also the main ReactBnbGallery component, the new way is doing the following:
import { ReactBnbGallery } from 'react-bnb-gallery';
const MyComponent = () => (
{ /* ReactBnbGallery wraps the Gallery component */ }
<ReactBnbGallery photos={[...]} />
);
The updates have been published in NPM with the new version 1.1.7.
Related
I am trying to build a system in nextjs where user can add their own react components with variables, functions, logics and I would like to store them in a database and then load those string component in my next application so they work at run time. Here is an example of what I am trying to do
const Home: NextPage = () => {
const Test = `export default function Test() {
return (
<div>
<h1>Testing component loading....</h1>
</div>
)
}`
return (
<>
<Test/>
<h1> this is a nice h1 tag</h1>
</>
)
}
export default Home
Here, Test is the an example component can assume coming from an api call. How can I load the logic and everything to work in my next application?
I have react jsx parser and other things, I was able to make jsx works, but didn't get success in making js code works or logics.
I want to add the power of react in the component as well not just jsx only.
Thank you.
Idea is
String from DB
=> server create JSX file from string
=> put JSX file into development env
=> create Route to that JSX file => server proxied to that Route
I'm quite new with reactjs, and I'm struggling with the following:
I have a Header component (in my App.js file) which contains an AudioPlayer. This AudioPlayer needs to be updated with current value of src (with the path of the song, stored in local) and title. Now, think about something like this:
App.js
function App(){
<Header/>
<Page1/>
<Page2/>
<Page3/>
...
<SomePage/>
...
<Footer/>
}
Header.js
import HeaderLogic from './HeaderLogic'
funtion Header(){
const {property1, property2, ..., path, title} = HeaderLogic()
//In HeaderLogic I want to get path and title, set in SomePageLogic.js
...
return <>
<AudioPlayer
src={path}
title={title}
/>
...
</>
}
SomePage.js
import SomePageLogic from './SomePageLogic'
import songPath from './somePath/songPath'
function SomePage(){
const title = 'songTitle'
const {property1, property2, ..., propertyN} = SomePageLogic(songPath, title)
//In SomePageLogic (or maybe here) I want to set path and title of the song,
//in order to be used from the HeaderLogic component
return <>
...
</>
}
I'm not sure useContext could be fine in this case, since I want to share data between unrelated components... Of course, the Header should rerender when it detects the song has been set. Should I use some kind of subscription pattern?
Any hint?
Thank you very much!
you can use Redux for storing your states. Basically React Redux is kind of a store where you can store your state and whenever it get updated it directly render html. you can access store state anywhere by using useSelector in hook, it get updated value whenever it changed by some other component
No need for any subscription pattern and definitely not using localStorage - context is exactly used for your usecase: sharing state between unrelated components.
So for instance, I want to share selected menu between the header and the Page1 somewhere below, you'd create a context with createContext(), export it's provider, wrap the children, and then you share that state between all components you set as children. Example:
const defaultSelectedMenu = 'a';
export const MenuContext = createContext({ selectedMenu: defaultSelectedMenu });
export const MenuProvider = ({ children }) => {
const [selectedMenu, setSelectedMenu] = useState(defaultSelectedMenu);
return (<MenuContext.Provider value={selectedMenu, setSelectedMenu}>
{children}</MenuContext.Provider>)
}
And then in your app.js:
...
<MenuProvider>
<Header />
<Page1 />
</MenuProvider>
<Page2 />
...
Now, your Header and Page1 components can access the MenuContext through useContext(MenuContext) and have access to the state and the mutator.
This was just a simple example but the same logic applies to any logic you want to share, heavy computation, API calls, you name it. You define the implementation in the <Provider> and then consume the implementation by accessing it through useContext
You can use localStorage.
Basically, it'll store your desired value in the browser. So, you can access it from anywhere within the application.
Apologies if this is a basic question but I am new to react/gatsby and i am struggling to find an answer to my question as i am not sure the exact terminology.
I am currently building a site using atomic design principles. i want to update the copy for atom components such as buttons/forms when they are used around the site - however i am struggling to pass data using the methods i know of.
Code set up
Atom/Button components the text is coded as such
<button>{this.props.copy}</button>
Layout component such as a hero banner The button is imported in the layout using
<section>This is a hero banner <button copy="copy goes here" /></section>
Page component I want to use the layout/hero component across various pages, I've imported the layout component and overwrite the button text already defined in the layout component however using
<layout copy="overwrite the copy"> obviously will not work
Is there a way to either pull a component into another component as it is called in such as <hero <button copy="new copy"/> /> and overwrite the prop. OR a better way to define props in the atom components that they can be nested. so the structure looks like this (the third level components are always in layouts and rarely pulled into the page by themselves.)
Page 1
Page 2
├── Layout (Hero)
├─────── Atom (button)
├─────── Atom (Input)
└─────── Atom (Select)
any help would be greatly appreciated.
You have a couple options here:
Prop Drilling
Render Props (React docs).
I am going to say avoid Prop Drilling as much as possible. It becomes cumbersome on large component hierarchies. Try a more dynamic approach with the render props that allows you swap out implementations with out causing issues.
Prop Drilling:
This would involve passing props down the component hierarchy. For your use case, it would look like this
class Layout extends Component {
render() {
return (
<section>
This is a hero banner <AtomButton copy={this.props.copy} />
</section>
)
}
}
class AtomButton extends Component {
render() {
return (
<button>this.props.copy</button>
)
}
}
Render Props:
What I am showing here is not actually a render prop. This is just passing a component down as a prop and then rednering the component. A true render props is defined in the React docs I linked.
class Layout extends Component {
render() {
return (
<section> This is a hero banner {this.props.button} /><section>
)
}
}
//Wherever your are loading your Layout Component
class Page extends Component {
render() {
return (
<Layout buttonRender={<AtomButton copy="overwrite copy" />} />
)
}
}
I am writing code to plug in an existing React component into another component.
The way it's been originally done in code is using a fragmentContainer.
I understand a fragmentContainer is a Higher Order Component that acts as a wrapper, and returns another React component.
However, I am trying to understand whether I really need to use a fragmentContainer to plug in my existing component, or I can create another wrapper component instead.
Is there a sure way of telling where a fragmentContainer should be used vs React Component within a React Component?
I have looked at the official docs(https://relay.dev/docs/en/fragment-container), and other resources, but it seems like either way can be used?
Are there special cases where fragment containers should be used?
You use a fragmentContainer to ensure what data you need in a component.
For exemple:
parent.js
const ParentComponent = ({list}) => (
<QueryRenderer
query={graphql`
query List {
id
...childComponent_item
}
`}
render={
list.map(item => (
<ChildComponent item={item} key={item.id} />
))
}
/>
);
export default ParentComponent;
// Here, in the parent component
// I need the id of each item of the list but I don't need the others values.
childComponent.js
const ChildComponent = item => (
<>
<div>{item.name}</div>
<div>{item.avatar}</div>
<div>{item.othervalue}</div>
</>
)
const ChildComponentWithFragment = createFragmdentContainer(
ChildComponent,
{
list: graphql`
fragment childComponent_item on ItemType {
name
avatar
othervalue
}
`
};
export default ChildComponentWithFragment;
// Here in the child component
// I need the others data of the Item object so i have to get these values
// in my fragment
I'm working on a project with React and react-router-v4, and
I'm trying to find a way to trigger a change of the route manually.
something like <Link to="/newpage"> component, which takes you to a new route.
but I want to do it manually from inside one of my methods,
something like this.router.location = "/newpage".
Use the this.props.history.push method that is exposed by the <Link> component or by the withRouter high-order component as PompolutZ mentioned in the answer above.
An example of such is <button onClick={() => this.props.history.push('/Home') } />
What about using withRouter high-order component?
https://reacttraining.com/react-router/web/api/withRouter
class GoToNewPageButton extends React.Component {
navigateToNewPage() {
this.props.history.push('/newpage');
}
render() {
return <button onClick={this.navigateToNewPage.bind(this)}>To the new page!</button>
}
}
const GoToNewPageWithHistory = withRouter(GoToNewPageButton);
Render a Redirect component which will navigate to the new location.
<Redirect to="/somewhere/else"/>
For more details check documentation here.