I need to render large text in some places and sometimes small descriptions on my website.
The text is not in English language what makes left-right vs right-left to be really annoying.
Moreover, the componenet containing the text became very large and hard to maintain.
I'm not a pro yet but i'm sure there is a best practice for my question.
Currently, my way to solve the large text is to render small components with the text only. (ofc I can create another api that includes the desired text but not in this case. I want to seek other way)
//folder contain MainCompoenent.jsx and TextComponenet.jsx
MainCompoenent:
import React from "react";
import TextComponenet from "./TextComponenet.jsx"
const MainCompoenent= () => {
return <div>
<ManyHtmlTagsandExtraLogic>
<TextComponenet />
</ManyHtmlTagsandExtraLogic>
</div>;
};
export default MainCompoenent;
TextComponenet:
import React from "react";
const text = `lorem but not in English language * 1000 `;
const TextComponenet= () => {
return <div>{text}</div>;
};
export default TextComponenet;
Not sure if you meant this with "I can create another API", but in my opinion, best way to handle this is have a component similar to the one you created, TextComponent, but make it reusable by using props.
Then, for an example, you can create one separate file called i.e. "alltexts.js", where you can either create (and export) one JSON object with all the texts that you need, or you can create a separate variable for each of your texts and export them.
Then on the parent component that calls the text component, you can import the "alltexts.js", and pass the specific text as props to the TextComponent like
<TextComponent text={myText} />
Related
I have a very large and complex React application. It is designed to behave like a desktop application. The interface is a document style interface with tabs, each tab can be one of many different type of editor component (there are currently 14 different editor screens). It is possible to have a very large number of tabs open at once (20-30 tabs). The application was originally written all with React class components, but with newer components (and where significant refactors have been required) I've moved to functional components using hooks. I prefer the concise syntax of functions and that seems to be the recommended direction to take in general, but I've encountered a pattern from the classes that I don't know how to replicate with functions.
Basically, each screen (tab) on the app is an editor of some sort (think Microsoft office, but where you can have a spreadsheet, text document, vector image, Visio diagram, etc all in tabs within the same application... Because each screen is so distinct they manage their own internal state. I don't think Redux or anything like that is a good solution here because the amount of individually owned bits of state are so complex. Each screen needs to be able to save it's current working document to the database, and typically provides a save option. Following standard object oriented design the 'save' function is implemented as a method on the top level component for each editor. However I need to perform a 'save-all' function where I iterate through all of the open tabs and call the save method (using a reference) on each of the tabs. Something like:
openTabs.forEach((tabRef) => tabRef.current.save());
So, If I make this a functional component then I have my save method as a function assigned to a constant inside the function:
const save = () => {...}
But how can I call that from a parent? I think the save for each component should live within that component, not at a higher level. Aside from the fact that would make it very difficult to find and maintain, it also would break my modular loading which only loads the component when needed as the save would have to be at a level above the code-splitting.
The only solution to this problem that I can think of is to have a save prop on the component and a useEffect() to call the save when that save prop is changed - then I'd just need to write a dummy value of anything to that save prop to trigger a save... This seems like a very counter-intuitive and overly complex way to do it.... Or do I simply continue to stick with classes for these components?
Thankyou,
Troy
But how can I call that from a parent? I think the save for each component should live within that component, not at a higher level.
You should ask yourself if the component should be smart vs dumb (https://www.digitalocean.com/community/tutorials/react-smart-dumb-components).
Consider the following:
const Page1 = ({ onSave }) => (...);
const Page2 = ({ onSave }) => (...);
const App = () => {
const handleSavePage1 = (...) => { ... };
const handleSavePage2 = (...) => { ... };
const handleSaveAll = (...) => {
handleSavePage1();
handleSavePage2();
};
return (
<Page1 onSave={handleSavePage1} />
<Page2 onSave={handleSavePage2} />
<Button onClick={handleSaveAll}>Save all</button>
);
};
You've then separated the layout from the functionality, and can compose the application as needed.
I don't think Redux or anything like that is a good solution here because the amount of individually owned bits of state are so complex.
I don't know if for some reason Redux is totally out of the picture or not, but I think it's one of the best options in a project like this.
Where you have a separated reducer for each module, managing the module's state, also each reducer having a "saveTabX" action, all of them available to be dispatched in the Root component.
Imagine you made a web framework that helps you quickly make blogs for clients. For the sake of this post, its the same blog template everytime, what changes is the content. You're React app is a simple structure of the following [where the Content state is just changing each time]
<App>
<Navigation/>
<Content/>
</App>
What makes the framework is you have XML files which contain the HTML. Each XML file represents one blog post. The app pulls all the HTML from the XML files, and puts it into the state of the App in a "blog posts" array. Depending on the state of the app, a specific entry in the array will be displayed in Content...
Content's state has a field called "html" which is what holds the HTML to be injected in string form. [you have to use dangerouslySetInnerHTML]
This concept works fine, and I have a version of it now. However, imagine you have a React components that you want to add to each blog post. Say you want to add the component into a specific blog post in a specific section. You want to add props to it and such. Now this goes out the window with dangerouslySetInnerHTML
This is where I am stuck trying to find the best direction to go. The only thought I have now is the following:
Since you would now be writing JSX in the XML, just make each blog post its own component. You would have ...etc and then if this.state.currentPost === 1 then display BlogPost1 and likewise. Yet you would have to have a huge block of if-statements depending on how many blogposts you have, and its not ideal to have to add everytime you have a new blogpost
When I read the title of your question I got curious and found this library to parse XML into React components: xml-to-react. But that's not what you are asking for.
As you want to use components in the middle of you string of HTML, I'll suggest: react-remarkable. This component compiles its children (a string with markdown/html/react) into react nodes.
Example from its docs:
var React = require('react');
var Markdown = require('react-remarkable');
var MyComponent = React.createClass({
render() {
return (
<div>
{/* Pass Markdown source to the `source` prop */}
<Markdown source="**Markdown is awesome!**" />
{/* Or pass it as children */}
{/* You can nest React components, too */}
<Markdown>{`
## Reasons React is great
1. Server-side rendering
2. This totally works:
<SomeOtherAmazingComponent />
Pretty neat!
`}</Markdown>
</div>
);
}
});
I'm looking for a solution how to position a component in a .jsx-file instead of a .css-file because I have multiple files of the same component, but each one is responsible for different tasks so I need them in different positions of the page.
I don't want to have multiple copies of the same file with only a minor change of the css class - I would rather like to add changes to the .jsx-file, or if you know how to achieve that using a .css-file, please let me know.
Example:
I have a 'Fish'-file which gives the basic structure of what the fish will look like.
I have to make multiple fish files(i.e fish.jsx, fish1.jsx, fish2.jsx) because they each use a different css class for their positioning. How can I reduce the amount of Fish.jsx to one either by adding to the original fish.jsx or .css-file used?
The way I would approach your problem would be something like this
import Fish from './Fish';
import './Fish.css';
// other stuff
const FishContainer => (
{[...Array(10)].map( (_, i) => <Fish className=`fish-${i}` /> )}
);
export default FishContainer;
And in your css file
.fish {
&-1 {}
&-2 {}
// etc
}
I'm working on a component that has many subcomponents, some of which are nested five deep. I'm interested in using redux for the advantage of having a single source of truth in a common state atom.
What I'm not understanding is the smart/dumb component recommendation and putting the provider above the main component and passing everything down via props. If I do this then I'd need to pass props down all the way to the fifth nested item so it can make a callback to dispatch an action or to look at some state that only it needs and not its parents. I understand this is for code reuse, but the subcomponents will never be used outside of the main component. What is the recommended solution here? Still use props?
Note: the author of this library requested we ask questions on StackOverflow. I'm mentioning this because SO seems to flag "best practice" questions as too vague.
While the answer matt clemens posted does cover this at a high level, but I'll try to go into more depth here.
You can use connect() at any level. Doing so makes the component smart, since it knows where its props come from. A dumb component just has props, and they could come from anywhere. A smart component is coupled to redux; a dumb component is not.
There are differing opinions on this approach, but it is supported and valid.
Where to draw this line is entirely up to you, but let's look at an example. You have some chat client with a standard sidebar component, a message window, and the entry field for sending new messages.
+---------+--------------------------+
| | |
|Sidebar | Messages window |
| | |
| | |
| | |
| | |
| +--------------------------+
| | New Message Entry **|
| | |
+---------+--------------------------+
The parent of all of these would use connect() to get the data from redux and feed it into these components via props. Now imagine that those two asterisks besides new message entry open up a settings panel (ignore the stupid placement, this is an example). Does it really make sense for new message entry to pass those props through? No, it doesn't.
To solve this you could create a special "container", lets call it SettingsContainer that used connect() to get its props and all it did was pass them down to SettingsPopup. SettingsPopup would not know about redux, and could still be tested/styled/reused normally, and the new message entry would only need to know about SettingsContainer, not any of its dependencies.
This approach scales well, but it has two penalties. First, the smart "wrapper" components like SettingsContainer have to be consumed by otherwise dumb components. This complicates the testing of the new message entry component. Second, the top-level component no longer exposes the entire graph of data dependencies, which makes things harder to reason about without delving deep into the component hierarchy.
These tradeoffs can be worth it, but you should be aware of them.
You can use the newer React feature of context, via using 'react-redux''s component Provider. Using Provider will abstract away some of the implementation details of context, makes your markup quite expressive imho.
You basically setup a mini-global property, that all sub-components, dumb or smart can reference:
import React from 'react';
import {render} from 'react-dom';
import {createStore} from 'redux';
import {Provider} from 'react-redux'; //Special Redux component to help
import {reducers} from './reducers.js';
var DeepDumbChild = (props, context) => (
<div>
<pre>
{JSON.stringify(data, null, 2)}
</pre>
</div>
)
class SmartChild extends React.Component {
render() {
/* Use the global-like context */
let data = this.context.store.getState();
return (
<div>
<DeepDumbChild data={data}/>
</div>
)
}
}
SmartChild.contextTypes = {
store: React.PropsTypes.object /* required */
}
/* No messy props :) */
var App = () => (<div>
<SmartChild/>
</div>);
render(
<Provider store={createStore(reducers)}>
<App/>
</Provider>,
document.getElementById('app')
);
UPDATE: If you want to try the approach below, have a look at https://github.com/artsy/react-redux-controller, which I recently published.
I think the best way to go is to map selectors to context at the root (container) component, rather than having a bunch of containers or using connect everywhere. I've done this in my own project and it's working beautifully. It adds a new pattern of annotating selectors with the PropTypes they produce. That let me use childContextTypes to allow all descendants to retain the same protections they have with propTypes. This is an advantage over Ashley Coolman's approach of passing down a big untyped object being passed down. I'm hoping to have time in the next couple days to factor it into its own library and publish.
In the meantime, I'd suggest making components smart, using connect liberally, rather than Tyrsius's approach of creating a whole bunch of containers, but that's just my opinion.
I have two Components of the same level (no owner-ownee relation). Suppose by clicking "C" in Component A, I set the temperature unit to "C", and clicking "F", I set the unit to "F". In Component B, I need to display the temperature, so I need to get the unit. But that information is in A. I wonder how I can access the state in Component A?
Follow up:
In another Component C, which is also parallel to A and B, I have a link to another page:
<div className="bottom_link">
<Link to={'weather-stations/eaB1rJytnpS5mZ2m'}>view detail</Link>
</div>
I also need to pass the unit info to that page. I wonder what is the recommended way to do this? Thanks.
Have all of your components, A, B and C, owned by component X and move the state there. Have a handler in component X that you pass into the children, and that handler will do a setStateon X.
An alternative is to use the Flux approach. Here you would use a store and have each component read from that shared store's state. The change from F to C and back would be done via an action creator and store handler.
The second approach is an extrapolation of the first: you are essentially 'lifting' the state up into the global scope with a store, whereas you are lifting it into X's scope by using X's state.
In general in React, you want your components to be as stateless as possible. Therefore I would recommend using the first approach. You can then lift the state higher if necessary (say X, Y and Z need to share the state) and A, B and C are left untouched.
Using props rather than state has the nice side effect of forcing you to think about the API of your components. Exactly what data does this component require to do its job? Then those requirements are passed as props.
If I were to give any single piece of advice to someone starting in React, it would simply to not use state whenever possible. Even when you think you need it, you can often remove it, so you should be trying as hard as possible to avoid state.
I'm working on an app with hundreds and hundreds of components, and I can barely think of a place where we use this.setState
The best way to do this now is with the useContext hook. Create a new file that can be called TemperatureContext.js. In there you will need the following:
import {createContext} from 'react'
export const Temperature = createContext(null);
//you can replace null with an initial condition
Then, in your app.js file import the file you made and create a useState value. Then, wrap both Component A and Component B in a provider tag:
import React, {useState} from 'react'
import{Temperature} from '.TemperatureContext.js'
function App(){
const [temperature, setTemperature] = useState();
return(
<Temperature.Provider value={{temperature, setTemperature}}>
<ComponentA>
<ComponentB
</Temperature.Provider>
)}
Then, in each of your components, you can import the temperature state by
import React, {useContext} from 'react';
import{Temperature} from '.TemperatureContext.js';
function ComponentA(){
const [temperature, setTemperature] = useContext(Temperature);
const tempChange(entry)=>{
...
setTemperature(entry)
}
return(
...
)
}
Now, by using the tempChange function in ComponentA, it will alter the state in everything that is wrapped within the Provider tags. Thankfully, react has advanced a long way since this question was posted.