score:10
i don't know typescript so i can't answer in the same language, but if you want your provider to be "specific" to your mylist
class, you can create both in the same function.
function makelist() {
const ctx = react.createcontext();
class mylist extends component {
// ...
render() {
return (
<ctx.provider value={this.state.something}>
{this.props.children}
</ctx.provider>
);
}
}
return {
list,
consumer: ctx.consumer
};
}
// usage
const { list, consumer } = makelist();
overall i think you might be over-abstracting things. heavily using generics in react components is not a very common style and can lead to rather confusing code.
score:3
i think the answer, unfortunately, is that the question doesn't actually make sense.
let's take a step back; what does it mean for a context to be generic? some component producer<t>
that represents the producer half of a context would presumably only provide values of type t
, right?
now consider the following:
<producer<string> value="123">
<producer<number> value={123}>
<consumer />
</producer>
</producer>
how should this behave? which value should the consumer get?
- if
producer<number>
overridesproducer<string>
(i.e., consumer gets123
), the generic type doesn't do anything. calling itnumber
at the producer level doesn't enforce that you'll get anumber
when consuming, so specifying it there is false hope. - if both producers are meant to be completely separate (i.e., consumer gets
"123"
), they must come from two separate contexts instances that are specific to the type they hold. but then they're not generic!
in either case, there's no value in passing a type directly to producer
. that's not to say generics are useless when context is at play...
how can i make a generic list component?
as someone who has been using generic components for a little while, i don't think your list example is overly abstract. it's just that you can't enforce type agreement between producer and consumer - just like you can't "enforce" the type of a value you get from a web request, or from local storage, or third-party code!
ultimately, this means using something like any
when defining the context and specifying an expected type when consuming that context.
example
const listcontext = react.createcontext<listprops<any>>({ onselectionchange: () => {} });
interface listprops<titem> {
onselectionchange: (selected: titem | undefined) => void;
}
// note that list is still generic!
class list<titem> extends react.component<listprops<titem>> {
public render() {
return (
<listcontext.provider value={this.props}>
{this.props.children}
</listcontext.provider>
);
}
}
interface customlistitemprops<titem> {
item: titem;
}
class customlistitem<titem> extends react.component<customlistitemprops<titem>> {
public render() {
// get the context value and store it as listprops<titem>.
// then build a list item that can call onselectionchange based on this.props.item!
}
}
interface contactlistprops {
contacts: contact[];
}
class contactlist extends react.component<contactlistprops> {
public render() {
return (
<list<contact> onselectionchange={console.log}>
{contacts.map(contact => <contactlistitem contact={contact} />)}
</list>
);
}
}
score:8
i had the same problem and i think i solved it in a more elegant way:
you can use lodash once
(or create one urself its very easy) to initialize the context once with the generic type and then call him from inside the funciton and in the rest of the components you can use custom usecontext hook to get the data:
parent component:
import react, { usecontext } from 'react';
import { once } from 'lodash';
const createstatecontext = once(<t,>() => react.createcontext({} as state<t>));
export const usestatecontext = <t,>() => usecontext(createstatecontext<t>());
const parentcomponent = <t>(props: props<t>) => {
const statecontext = createstatecontext<t>();
return (
<statecontext.provider value={[your value]}>
<childcomponent />
</statecontext.provider>
);
}
child component:
import react from 'react';
import { usestatecontext } from './parent-component';
const childcomponent = <t>(props: props<t>) => {
const state = usestatecontext<t>();
...
}
hope it helps someone
Source: stackoverflow.com
Related Query
- How to create a generic React component with a typed context provider?
- How do you correctly use React.lazy() in Typescript to import a react component with a generic type parameter?
- How to read console.log from a mounted component with Enzyme and Jest in Create React App
- How to create a link in React component with onClick handler?
- How to type a Typescript React Component that accepts a Context with a super-set of properties
- How to test a React component that uses context like in react-router 2.0 with Jest 0.8.x
- Is it possible to create a generic React list component with typescript?
- How can I use a React 16.3 Context provider with redux store?
- How to write to apollo cache from within React component with out losing context of "this"
- How to make a functional React component with generic type?
- How to mock React Context for testing component with jest
- How to create Generic event handler with React TypeScript
- How to create React component with components inside it?
- How to create React Context that passes a function with Typescript
- How to create a generic arrow function with react and typescript
- Create a generic context with a state from parent component using TypeScript
- How to create a dynamic, custom React Table Component with action and status buttons
- How to create a reusable Input component with React & TypeScript?
- How to create a Tabs component with React
- How to properly use React Context Provider with Typescript?
- How can I create a React component with a variable?
- How to create multiple swiper instance in a react component and control one with the swipe of another?
- How create React Typescript component with required and optional values but required value without default value?
- How to call useEffect by updating values in a Context provider with react testing library?
- How can I create multiple instances of a React component (having an infinite animation) with different values for the :root variables
- How do I make a React prop only required when used in the context of a Container component with Typescript?
- How can I create a parent component for specific pages (to be able to add react context inside parent)?
- How to create a ref to child component, store it in context and pass it to a sibling in React with Material UI
- How can i test with jest a react component who use context api?
- How to create a HOC component in react validated with typescript
More Query from same tag
- Compute HMACSHA256 in .net equivalent to reactjs
- How do I share state between react native screens?
- Who is supposed to pass 'handleSubmit'
- Loading a local React app inside WKWebView iOS
- Get page location with React Router 4 and Hash routing
- React doesn't send entries to DOM
- Rollup Build failure for SCSS exports to be used in TS ( [!] Error: 'default' is not exported by src/styles/variables.scss )
- Background image not showing up with React + TailwindCSS
- In Flux what is responsible for direct talking to API
- Time Spent by user on a web page + Iframe
- Material ui Select change background and focused color
- Put Border Color React Material Theme
- react-admin Create a custom page which can be accessed from menu sidebar
- System notification for hot module replacement WebPack ZSH
- How to toggle a content of the single element in React JS?
- React - Getting "Component definition is missing display name" error when using React.memo
- Why aren't my images from local folder loading?
- How to access array of objects from the api in react js.?
- Dynamic class name in React issue
- React-router-v6 nested route only renders main route
- × Error: Invalid hook call. Hooks can only be called inside of the body of a function component.[ReactJS]
- webpack umd lib and external files
- Passing data from child to parent after Array State has been updated, Why am I getting an instance of the prev state?
- todos array at index 1 always get changed and the array doesn't move further - React-Typescript
- How can I dynamically create a component based on a prop or variable using React.createElement
- Slider functionality JavaScript
- React-Three-Fiber (R3F): GLTF loader loading issue. Why can't I see my model?
- React onSubmit method only populates on second event
- Page does not retain its state on re rendering
- Problem with event.target.value in react getting 11 not 1+1