FragmentContainer vs just another React component as a wrapper? - reactjs

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

Related

Is it possible to pass data to components without a parent?

I understand that the normal way is to pass props through a parent, but I want to know how else I can pass props to a component.
let C1 = createReactClass({
...
render: function() {
console.log('render C1');
return (
<div>
<button onClick={this.cambiaAAzul}>Azul</button>
<button onClick={this.cambiaAVerde}>Verde</button>
<button onClick={this.cambiaARojo}>Rojo</button>
<p>Estado C2 <strong style={ {color: this.state.color} }>{this.state.color}</strong></p>
<C2 color={this.state.color}/> // It is common
</div>
);
}
});
Typically, to solve the props-drilling problem, which is what seems to be the issue you are trying to solve, the useContext hook should help.
So set up a context,
const C1ContextProvider = ({children}) => {
//...
// the Provider gives access to the context to its children
return (
< C1Context.Provider value={someValue}>
{children}
</C1Context.Provider >
);
}
... and then in your component where you need someValue, you can just do this:
import React, { useContext } from "react";
import { C1Context } from "../C1Context";
//...
const values = useContext(AirDCPPSocketContext);
cons foo = values.someValue; // <-- someValue obtained from the context
//..
I don't know how it is possible to not have parents but you can pass informations by local storage and context hooks.
Props are by definition arguments passed into a React component. Since React components are instantiated in the context of their parent, I'm not sure if it would be possible to pass props in any other way.
There are many other ways to get data in React though. You could query data from an API or other source, or you could pull from a state manager (such as redux). It just depends on what you are trying to accomplish.
Props are simply things passed into a component when it's called.
For instance:
C1.js
function C1((prop1, prop2) {
<h1>{prop1} {prop2}</h1>
})
App.js
<C1 prop1="Hello" prop2="World" />
<C1 prop1="React's" prop2="Great" />
By referencing the C1 component in App.js, you can call it with different props to produce different results.
Now I'm not too familiar with the createReactClass and render: you're using, as this is a style of React I've never learned. However, I'd guess that props provide the same function.
Your question asks about props without a parent. Well. Props without a parent wouldn't be props, they'd just be normal JS data types inside your file.
Hope this helps :)
The component's local state only can drill into child components. for passing props without using React component's local state. you have to use state management libraries like Context API or Redux
These libraries are created to make you able to pass props into nonrelated or sibling components
Example with redux:
Here I Assume that you set up redux in your project. imagine you have two components that you want to pass props without parent-child relation.
const changeMyWeightAction = (weight) => {
return {
type: 'CHANGE_MY_WEIGHT',
payload: weight
}
}
const JenniferFunctionComponent = () => {
const dispatch = useDispatch()
return (
<div>
<span>hello I'm Jennifer and I can decide my weight</span>
<input onChange={e => dispatch(changeMyWeightAction(e.target.value)})/>
</div>
)
}
const WeightFunctionComponent = () => {
const weight = useSelector(state => state.Jenny.weight)
return (
<span>Jenny's weight is {weight}</span>
)
}

Composition In React with params

I am trying to create an architecture that in some way imitates the slots from VUE.
The idea is for the parent component to be able to inject some props into the component and the child can inject the rest of the props.
This is how I tried to approach this problem, unfortunately this approach will not work because the compontent will be "monut" every time the parent re-render takes place.
Filters = (prams) => {
useEffect(()=>{ //RENDER ALL THE TIME },[])
...
}
ParentComponent = () => <ChildComponent Filters={(props) => <Filters propA={"A"} />}
ChildComponent = (props) => {
const Filters = props.Filters;
render(<Filters probB="B" />)
}
I know, I can use useCallback for ((props) => <Filters propA={"A"} />), but only it will help only if what I want to pass to "propA" is steady.
I want to "manage" <Filters /> component in parent, so that the child does not have to handle Filters logic (props).
React gives you proper API to do most things. Using it forces you into certain paradigms that are proven to work well.
You should probably have a look at the Context and Memo APIs from React.
Or if you have to select and update state from multiple components, you might wanna have a look at libraries that provide global state, like Redux and Recoil.
Context example
// The shape
interface ContextProps {
myProp: string
}
// The context
export const MyContext = React.createContext<Partial<ContextProps>>({
myProp: 'nothing'
});
// The provider
<MyContext.Provider value={{ myProp: 'override' }}>
{children}
</MyContext.Provider>
// Consumer
const { myProp } = useContext(MyContext)
In some case you can also use useMemo or React.memo and use your own custom compare function if needed to prevent re-renders in very specific situations.

NextJS: data fetching in child component and pass to parent component

I am new to Next.js and trying to make an e-commerce project. I am stuck on if a child component Sort Component has a post request to the server to filter the data and pass it back to the Products component as product props.
The folder structure is like this:
<>
<Sort />
<Products products={products} />
</>
Inside the Sort component, I will send the filter parameters back to the server. So the method I am thinking of is using Redux, but can I use the useSWR hook? As the action is taken at Sort component, seems useSWR hook need to have the action and the data returned together in the same component, is that correct?
Your code is looks like that:
<>
<Sort />
<Products products={products} />
</>
In this case you have to create a shared state in the container of that two, like this:
1, You can use a simple shared state, like:
function ContainerOfTwo(props) {
const [sharedState, setSharedState] = React.useState({});
return (
<>
<Sort setSharedState={setSharedState} sharedState={sharedState} />
<Products products={products} setSharedState={setSharedState} sharedState={sharedState} />
</>
)
}
2, Use the native React contextAPI maybe with useReducer. (This is a smaller and more specific state management. Small resource)
3, Use Redux. (For larger, and more robostus state handler)
Summary: I would go with shared state for the first, if thats not enought with your requirements, go with the contextAPI or with redux depending on your needs.
If you doing good, should not be a large issue to hold the state to contextAPI/redux.
The simplest solution, although perhaps not the best in the long term depending upon how complex the interactions between these child components can get, is managing the state and passing state and hooks to set the state to these children.
function ParentComponent(props) {
const initialState = {};
const [ sortedData, setSortedData ] = React.useState(initialState);
return(
<>
<Sort setSortedData={setSortedData} />
<Products sortedData={sortedData} />
</>
)
}
Note: Since the Products component is dependent upon the sortedData to be updated you may want to set conditions on its render as you await the async fetch in Sort.
Again, if there will be any degree of complexity beyond this then you may want to use Redux or React's ContextAPI to manage the state. For example, if sortedData is used in any child components of Sort or Products then you'd want to manage using Redux or ContextAPI so you're not passing it along child to child.
You can read more about the useContext hook here: useContext
You can use callback method from parent to child and setting the state value in the parent and passing this value to other child components.
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
products: []
};
}
callBackMethod = (products) => {
this.setState({products})
}
render() {
const { products } = this.state;
return (
<>
<Sort callBackMethod={this.callBackMethod}/>
<Products products={products} />
</>
);
}
}
export default Parent;

Best way to handle the re-rendering in reusable components

I would like to create my own reusable components that can be used in other projects (as npm package).
Let assume that the reusable components are structured in this way:
ui
├───card.jsx
├───card-board.jsx
├───card-body.jsx
├───sliding.jsx
├───sliding-board.jsx
├───sliding-body.jsx
├───img.jsx
├───remove.jsx
├───title.jsx
└───index.jsx
Usage Example:
this.state.Cards.map(card => {
return (
<Card key={card.id}>
<Remove onRemove={() => this.handleCardRemove(card.id)} />
<Img />
<CardBody>
<Title>{card.title}</Title>
<p>{card.body}</p>
</CardBody>
</Card>
);
});
It worked great until the number of cards are overpopulated. All the update and delete function became really slow due to the waste re-rendering on the same static content.
And of course this can be optimized by checking the previous and the new props on the Card component as below:
import React from "react";
import { CardContainer } from "./card.style";
import { deepCompare } from "../../utils/";
const Card = ({ children }) => {
return <CardContainer>{children}</CardContainer>;
};
// if return true - Card component won't re-render
const arePropsEqual = (preProps, newProps) => {
return deepCompare(preProps, newProps); // <- function that compare the nested props.
};
export default React.memo(Card, arePropsEqual);
As you can see. I'm using React.memo to control the re-rendering and I also implemented the deepCompare function that will return true if both input props are the same.
So, I would like to know what is the best way to handle this kind of problem in the large scale where there are a lot of components (probably nested).
And, Should the above solution(React.memo) be applied for each individual ui component that I created?. Because some of the ui element can be used individually without depending on some kind of container eg: Img, Remove and Title component.

How to deal with the props and tightly coupled components in React?

I have a couple components which are tightly coupled to each other. The highest component receives prop called options. The prop options is passed down through next components and so on.
Which is the best way to emit changes from nested components to each others? I wouldn't rather use redux in this case.
This example will work for React16.3 and above.
Click here to check working example.
a) Get Data from parent component to nested chid conponent using context api of react
1. Grand Parent Component
Context lets us pass a value deep into the component tree without
explicitly threading it through every component. Create a context for
the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// Use a Provider to pass the current theme to the tree below.
// Any component can read it, no matter how deep it is.
// In this example, we're passing "dark" as the current value.
const theme = "dark";
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
</ThemeContext.Provider>
);
}
}
2. Parent Component
A component in the middle doesn't have to pass the theme down
explicitly anymore.
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
3. Child Component
function ThemedButton(props) {
// Use a Consumer to read the current theme context.
// React will find the closest theme Provider above and use its value.
// In this example, the current theme is "dark".
return (
<ThemeContext.Consumer>
{theme => <div>{theme}</div>}
</ThemeContext.Consumer>
);
}
Replace theme to options in your case.
For more detail take the reference of react doc. Click here
b) Store data from parent component to store and get it in nested child component using redux
Here you are getting data from state and passing options data to
your component
const mapStateToProps = (state) => ({
options: state.options,
});
Here you are connecting your component from state
export default connect(
mapStateToProps,
null,
)(ChildComponent);

Resources