I have a certain component named ThemeDoc inside this component there is a context, localStorage, hooks, maps and whatnot, but in the end I get the value of the hooks inside a component named SideBar. I decided that there is no need to demonstrate the contents of the ThemeDoc component in order not to complicate my code and question, but I will attach a link of my project on the github if you want you can see GitHub Project. So as I just mentioned, I get the value of the hooks from the ThemeDoc component for the SideBar component, they look like this
const {SideBarValue, SideBarWallpaperValue, SideBarColor} = React.useContext(CounterContext);
const [SideBarTheme, SetSideBarTheme] = SideBarValue;
const [SideBarBackground] = SideBarWallpaperValue;
const [SideBarColorTheme, SetSideBarColor] = SideBarColor;
These values are used to change the color of the SideBar.
<div style={{background: SideBarTheme}}>
...
</div>
It all looks like this
Please see there are two values for SideBarTheme and SideBarColorTheme, SideBarTheme changes the background of the site to a gradient and the SideBarColorTheme only changes the SideBar color. As you can see I successfully applied the SideBarTheme value inside jsx and everything works fine for me
<div style={{background: SideBarTheme}}>
...
</div>
But I can’t use SideBarColorTheme, I don’t know how to do it, here is my full-fledged code if you need to tell me I will provide the ThemeDoc component
SideBar.jsx
function SideBar(props) {
const {someValue} = useContext(SideBarContext);
const {SideBarValue, SideBarColor} = React.useContext(CounterContext);
const [SideBarTheme, SetSideBarTheme] = SideBarValue;
const [SideBarColorTheme, SetSideBarColor] = SideBarColor;
return (
<div style={{background: SideBarTheme, backdropFilter: `blur(${someValue}px)`}}>
...
</div>
);
}
Related
I'm in a learning phase of react and I've been trying to nest style of parent in component in child component via class in react.js. How to do it?
What I've tried until now:
function Card(props) {
const classes = 'card' + props.className;
return (
<div className={classes}>
{props.children}
</div>
)
}
export default Card
I applied style on class 'card' in a CSS file.
Parent component JS code:
import Card from './UI/Card';
function ExpenseItem(props){
return (
<Card className="expense-item">
<ExpenseDate date={props.date} />
<div className="expense-item__description">
<h2>{props.title}</h2>
<div className="expense-item__price">{`₹ ${props.amount}`}</div>
</div>
</Card>
)
}
Now, there are various classes in parent component that are styled accordingly. And I'd like to nest those classes in child component for those style to work.
You can see in the code the way I tried to nest the classes, but it isn't working.
const classes = 'card' + props.className;
What am I doing wrong? And how should I correct it?
You missed a space after the card class name, otherwise i don't see any other issues in your code. Try below, hope it works
const classes = 'card ' + props.className;
Just one note, this will make your components dependent on each other. One of best things about React is that it allows you to have separation of concerns. So Card component is doing Card component staff, displaying some information and needs not be dependent on a parent in this case ExpenseItem.
One way to do it is to use styled-components.
I'm trying to add style to an element in my return of a react component, but I want to achieve this without adding a class. My text editor auto fills a style option, but I believe the syntax is wrong, since when trying to add a function on an onClick event, its a little different when its in the return of a react element. For example, instead of
onClick=function()
its
onClick={() => {function()}}
I'm hoping that instead of style={"background-color: green;"} its a different syntax to actually allow style changes once it hits the dom.
In-line styles can be done, and here is a code example as you have not provided one.
for example, lets inline style an h1 tag
<h1 style={{background-color:'green', color:'white'}}>This is a tilte</h1>
more can be found here
additionally, I would not recommend inline styling as it's not industry-standard and can cause your code to become bloted.
Style tags in react can indeed contain a references to functions.
I am not fully sure if you are working with React component classes or component functions, but your syntax can besides as follows. Create a variable called customStyle which will contain a function that returns your required style object:
customStyle = () => { return { color: 'red' } };
You can then reference customStyle inside markup as follows:
<div style={this.customStyle()}>My Element</div>
idont know if i understood your question well, You can achieve what you want by making a style state, then mutate it whatever style you want with setState
const [style, setStyle] = useState({})
const App = () => {
return <div style={style}>
<button onClick={() => setStyle({color: 'red'})}>handler button </button>
</div>
}
I have this component imported that returns a bunch of cards but I want to style this in a row instead of a column and it seems the way to do that is to loop the component as a <li> and then adding css but I cannot seem to make the component loop correctly.
the component looks like this inside of the parent element:
<div id="newsFeed" className='feed'>
<Feed theme={this.state.theme} articles = {this.state.articles} />
</div>
I have tried solutions such as:
var feedContent = <Feed theme={this.state.theme} articles = {this.state.articles} />
///////////////////////
{feedContent.map(item => <Feed key={item} value={item} />)}
</div>
but cannot seem to find any luck.
Any help would be greatly appreciated
map is a built in array method that is used a bunch in React. You need to use it on an array or else you will throw an error. I am assuming the value for articles is an array here:
//Feed component
class Feed extends React.Component {
constructor(props) {
super(props);
this.state = {
articles = []
};
}
componentDidMount = () => { // maybe call an API to populate the articles array }
render = () => {
return (
<ul className="someClass" >
{this.state.articles.map((item, index) => <li key={index} className="someOtherClass">{item}</li>)}
</ul>
);
}
}
alternatively you could create a li component, perhaps called FeedItem, import it and map it with the value prop from each item in the articles array.
// render method for Feed Component
render = () => {
return(
<ul className="someClass">
{this.state.articles.map((item, index) => <FeedItem key={index} value={item} />)}
</ul>
);
}
// FeedItem component
const FeedItem = ({value}) => {
return(
<li className="someOtherClass">{value}</li>
);
}
so, you are using map to create a list with the items in your articles array, and the map function loops through each article and returns a list component. Hopefully this helps! here's the React docs for reference: https://reactjs.org/docs/lists-and-keys.html
note: React docs advise against using an index as a key, but I don't know if your article array elements contain something unique. If they do (like an id of some kind), use that instead of index.
I think you need to change the approach.
I'd recommend you create an Article component, example:
function Article({ title }) {
<div>
{title}
<div>
}
After that, you might use the articles array to show each one:
//Feed component
this.state.articles.map((article, i) => <Article title={article.title}>)
In that way you can stylize the articles component as you want.
I was able to figure it out with simple CSS believe it or not. Basically <Feed /> was wrapped in a div in the parent component and was not responding to Flexbox CSS code, however, After I used changed the className of the div that was wrapping the component inside of its <div> within its own file the div responded to CSS! Thank you so much for your help everyone, I appreciate it!
Have you tried adding a className to the div that is the parent of the cards? Use that class to apply a flex display for example, and see what that gives you. If Newscard has a fixed width of 100% by chance, of course you'll need to adjust that to a small percentage / width to suit your needs.
Edit:
I figured it out & posted answer below.
Original Question
I am trying to create a completely compartmentalized web application within a shadow-dom and I've been using Antd components and ran into the issue where Antd is appending drop-down options into the body tag instead of as a child of the element that React is rendering into.
To isolate this issue I've removed everything outside of just React.render & a single Antd element which still does the same thing.
I then used a different component, "react-date-picker", which works how I had hoped Antd did, where the component renders as a child of the div specified for react.
Unfortunately, Antd rendering to the body of the HTML instead of as a child makes using shadow-root pointless.
Essentially my question is:
Is this Antd's normal functionality? If not then what might I be screwing up to have this happen? If so then is there a built-in Antd option that I'm missing that will render Antd options as child elements? If that option doesn't exist within their libraries, is there a way for me to force Antd to render as a child of my shadow-root node?
Here is what I'm using to render the Antd DatePicker component:
import ReactDOM from 'react-dom';
import React from 'react';
import DatePicker from 'antd/lib/date-picker';
ReactDOM.render(<DatePicker/>, document.getElementById('entry-fields'));
Before clicking on the Antd date picker:
After clicking on it, drop down options are appended to <body> and not <div id="entry-fields>:
Here is what I'm using to render the react-date-picker component to demonstrate the functionality I expected / need:
import ReactDOM from 'react-dom';
import React from 'react';
import DatePicker from "react-datepicker";
class Example extends React.Component {
state = {
startDate: new Date()
};
handleChange = (date: any) => {
this.setState({
startDate: date
});
};
render() {
return (
<DatePicker
selected={this.state.startDate}
onChange={this.handleChange}
/>
);
}
}
ReactDOM.render(<Example/>, document.getElementById('entry-fields'));
Before clicking on the react-date-picker date picker:
After clicking on the react-date-picker date picker (the drop down options are appended as children of the element react is rendered onto):
Basically I expected Antd to render its options encapsulated within the React rendered into <div></div> but it is instead appending elements on the <body></body>.
I'm relatively inexperienced in the web-dev domain and have resorted to asking a question here after way too much time trying to find the answer on my own. I am getting extremely frustrated in web-dev in general where any question seems to yield hundreds of irrelevant medium blog posts that are not useful in any capacity... assuming that it's not just me not knowing what to search for yet to find the answers I need which could very well be the case.
Really appreciate any help in advance.
Not sure how I managed to miss this but Antd has a parameter called "getCalendarContainer" which if left blank will render options into the body of the document but if supplied with the correct parameters will render the child elements into the container of your choosing.
Going off this example: https://react-component.github.io/calendar/examples/getCalendarContainer.html
I got it working by adding this function to my component:
getCalendarContainer()
{
return this.d || document.getElementById('calendarContainer');
}
and adding this to the component in JSX:
<div id="calendarContainer" ref={n => (this.d = n as HTMLDivElement)} >
<DatePicker onChange={EntryFields.onDateChange} getCalendarContainer={this.getCalendarContainer}/>
</div>
and initializing the div tag to reference it in the component's constructor like this:
private d: HTMLDivElement;
constructor(props: any)
{
super(props);
this.d = document.createElement("div");
...
It's also worth noting that the above will not work immediately when using shadow-DOM since you need to access the node that the shadow-DOM is a child to and then use getElementById().
Something along these lines (but probably better written I hope lol)
getContainer() {
let elem = null;
let shadowContainer = document.getElementById('entryFieldsShadow') as HTMLInputElement;
if (shadowContainer != null) {
let shadowDom = shadowContainer.firstElementChild;
if (shadowDom != null) {
let shadowRoot = shadowDom.shadowRoot;
if (shadowRoot != null) {
elem = shadowRoot.getElementById("entryFieldsContainer")
}
}
}
return elem || this.d;
}
where the JSX with react-shadow's shadow root is included looks like this:
return (
<div id="entryFieldsShadow">
<root.div>
<div>
<div id="entryFieldsContainer"/>
<style type="text/css"> #import "static/1.css"; </style>
<Layout>
<Content>
{this.RowCols()}
</Content>
</Layout>
</div>
</root.div>
</div>
)
This solve my problems
<DatePicker
{...}
getCalendarContainer={triggerNode => triggerNode.parentNode}
/>
I'm having trouble finding relevant documentation on how to remove UI components when using react. For example, there's a login form. The user clicks submit and now the form should be removed from the screen. How do I do this?
I've found unmountComponentAtNode, but that can only be invoked at the parent level. Am I supposed to have a parent node that is aware of all child state and loads them conditionally? Should all children have an "isHidden" attribute which renders the dom as hidden if true?
This must be basic but I don't see this in the react js tutorials. I found this stackoverflow post (react.js: removing a component) is this really the pattern? It kind of makes sense but it means that a large app will likely have an extremely complex Application parent class that manages maps of application state based on configuration.
It seems like i need to start defining application state as named maps. For example:
BaseApp: showHeader=true;showContent=true;
LoginState: showBaseApp=true;showLoginForm=true;
LoggedInState: showBaseApp=true;showFeed=true;
At any moment we would have to update all state maps and call the base class render method...
In my opinion your question isn't about removing component but about showing the right component. And yes - it can be done with a component state but with Flux/Redux store/reducer as well.
In your example with a login form after click on "Submit" we can change local state for the component and show another text like "The request was sent blah-blah-blah" or another component.
But you can do this by extracting component's local state to a store/reducer and it'll be work better in relatively big app. Nevertheless, it's really up to you where you want to store state.
I like to use a hide prop like so.
class AppCtrlRender extends React.Component {
render() {
let page = this.state.appState.currentPage;
let hideAbout = (page != 'about');
let hideHome = (page != 'home');
return (
<div id='AppCtrlSty' style={AppCtrlSty}>
<div id='allPageSty' style={allPageSty}>
<AboutPage hide={hideAbout} />
<HomePage hide={hideHome} />
</div>
</div>
);
}
}
export default class AboutPage extends React.Component {
render() {
if (this.props.hide) return null;
let aTime = (new Cache()).time.toString();
return (
<div style={AboutPageSty}>
React 0.14 ReFlux used for app state. This is the About Page.
<NavMenu /><br/><br/>
{aTime}
</div>
);
}
}