Is it possible to create an "HOC" which adds markup in Vue? - vue.js

In React, I would often construct HOCs which would wrap a component with some bit of markup. For example,
const WithLabel = WrappedComponent => ({ label, ...props }) => (
<label>
<div>{label}</div>
<WrappedComponent {...props }/>
</label>
);
Is there an equivalent construct for this sort of thing in Vue? I've read the documentation on mixins and slots and have seen many examples and read articles on how others are creating HOCs in Vue. But none of the examples or libraries I've seen seem to be able to handle markup decoration.

Related

Is it possible to globally define links to use a specific component?

I'm currently trying to use Nav with react-router. The default behavior reloads the page, so I'm trying to use the Link component from react-router-dom.
It's quite difficult to preserve the default styling when overriding linkAs.
Is there any global way to override link navigation behavior?
Like defining a global link render function, which I can then set to render the Link component from react-router-dom?
Yes, it's possible!
2 things are required:
Make a wrapper component that translates the Nav API to react-router-dom links.
Specify the linkAs prop to the Nav component.
Wrapper component
This is a simple component that creates a react-router-dom link while using styles from Fabric:
import { Link } from "react-router-dom";
const LinkTo = props => {
return (
<Link to={props.href} className={props.className} style={props.style}>
{props.children}
</Link>
);
};
Specify component for use in Nav
<Nav groups={links} linkAs={LinkTo} />
Have also created a full working example at https://codesandbox.io/s/xenodochial-wozniak-y10tr?file=/src/index.tsx:605-644

How to add data-testid attribute to react-select components

Using react-testing-library, I wish to test a form implemented in React.
That form includes a React component of type react-select.
It is necessary to click a part of the react-select component that has no label, no text, etc. (E.g. the dropdown arrow).
Ordinarily, the react-testing-library way to do this is to add a 'data-testid' attribute to the item in question.
I've found that it's possible to give each part of the react-select a CSS class attribute, by providing the 'classNamePrefix' prop to the react-select component. Is there some way to do the same for data-testid attribute?
Note: I'm aware I can provide custom implementations of the components of react-select, but that seems like overkill to get one attribute in place.
First of all I'd question why there's no label on the Select as this wouldn't be classed as accessible for screen readers.
But, If you don't want a visible label you could always pass an aria-label prop to the Select and test it that way using getByLabelText.
<Select aria-label="Example Label" ... />
getByLabelText('Example Label')
If you really need to add a data-testid you could replace the specific components you want to add the data-testid too and add it. (See the docs for more info)
e.g.
// #flow
import React from 'react';
import EmojiIcon from '#atlaskit/icon/glyph/emoji';
import Select, { components } from 'react-select';
import { colourOptions } from './docs/data';
const DropdownIndicator = props => {
return (
<components.DropdownIndicator {...props}>
<span data-testid="DropdownIndicator">
<EmojiIcon primaryColor={colourOptions[2].color} />
</span>
</components.DropdownIndicator>
);
};
export default () => (
<Select
closeMenuOnSelect={false}
components={{ DropdownIndicator }}
defaultValue={[colourOptions[4], colourOptions[5]]}
isMulti
options={colourOptions}
/>
);
Codesandbox link
Before all react-select is just a select. In testing you should keep eyes in your components. react-select is a component outside your project, the test cases belong to their owner.
So in this cases I recommend to just mock the package in your benefit.
Here is an example of how to mock it:
jest.mock('react-select', () => ({ options, value, onChange }) => {
return (
<select data-testid="react-select-mock" defaultValue={value} onChange={onChange}>
{options.map(({ label, value }) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
);
});

Styling multiple style props with styled-components on React Native

I have been using Styled-components with React web for a while now, but recently I have started working on a React Native app which I decided to use styled-compoents in. It's been great when styling components that have just the style property, such as the default react-native components.
The problem I've been having though is when I need to style a more complex component that has multiple style properties such as containerStyle, inputStyle, and others.
When it's only one style property with a different name I can do the following:
const StyledBadge = styled(({ style, ...rest }) => {
return <Badge {...rest} containerStyle={style} />;
})`
position: absolute;
right: 0;
top: 0;
`;
This works flawlessly but when the component has multiple styles, I have no idea what to do:
const StyledList = styled(({ style, ...rest }) => {
return <List {...rest} containerStyle={style} searchInputStyle={?} searchItemStyle={?} />;
})`
`;
With components like Gifted-React-Native-Chat is even worse because it has properties for passing properties as objects to its internal components, such as messageProps, listViewProps, containerProps and all of them have the style property.
Does anyone have any idea how to do that or if it's even possible?
I've been searching and trying to find a solution for this for a few days but I can't.
Thanks!
Here's how we ended up doing it.
Styled-components only work with the style prop but many custom components don't expose this prop. Instead they provide a *Style prop that gets passed to child component style props.
As an example, react-native-material-textfield has 5 style props.
We use the attrs function to keep the organization of styles in one file with the rest of the styled components.
This doesn't allow you to use traditional css syntax for the pseudo component, but it's the best we could think of to keep all styles organized.

Rendering stenciljs stateless components

I've been using StencilJS for some time now,
and coming from React background, my immediate instinct for writing some components is to write them stateless.
However, the stencil documentation doesn't mention the stateless components at all.
That's why I am writing here to learn other people experience with it
You should look at functional components: https://stenciljs.com/docs/functional-components to create stateless components, and they:
aren't compiled into web components,
don't create a DOM node,
don't have a Shadow DOM or scoped styles,
don't have lifecycle hooks,
According to the doc, if a component has to hold state, deal with events, etc, it should probably be a class component. If a component's purpose is to simply encapsulate some markup so it can be reused across your app, it can probably be a functional component
You can write functional components inside Stencil elements. As an example:
#Component({
tag: 'my-app',
styleUrl: 'my-app.css',
shadow: true
})
export class MyApp {
render() {
return (
<div>
<Loading />
</div>
);
}
}
const Loading = () => {
return (
<div class="loading">
<h1>Activating Santa</h1>
<span>🎅🎄🎁</span>
</div>
);
};
In this case <Loading> is a stateless functional component similar to React's model - you can obtain its props and get children, etc.
Stateless Stencil components can not be exported as top-level Web Components - those must be defined as classes.

Best practice to be DRY in terms of style in React Native with components such as TextInput?

I am using TextInput in multiple scenes to render "form" elements. They all share the same style, so what is good practice in React Native in terms of styling? I mean, I could define a style for the TextInput in every single component scene, but is there a way to be more DRY?
Wrap your TextInput in your own component. Add styles to it, and define props that you use a lot with that component. You can also pass other props (not explicitly defined) for example by using const { label, value, placeholder, onChange, multiline, onSubmit, ...passProps } = this.props; and then <TextInput label={label} ... {...passProps} />.