react-select component, not rendering - reactjs

react: ^15.4.2,
react-select: ^1.0.0-rc.10,
Example.tsx
import * as React from 'react';
import Select from 'react-select';
// Be sure to include styles at some point, probably during your bootstrapping
import 'react-select/dist/react-select.css';
var Select = require('react-select');
var options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
];
function logChange(val) {
console.log("Selected: " + JSON.stringify(val));
}
export class Example extends React.Component<any, any> {
render() {
return (
<div>
<Select name="form-field-name" value="one" options={options} onChange={logChange}/>
</div>
);
}
}
No errors reported at compile time.
Get an error message when attempting to render it
React.createElement: type is invalid -- expected a string (for
built-in components) or a class/function (for composite components)
but got: object. Check the render method of Example.
in Example
Being this is my first react project I have no idea how to debug this. I do not see anything wrong with this code.
Here is my render out of main.tsx
(() => {
const container = document.querySelector('#container');
render( <Example />, container);
})();

Well, from the example above which is copy-pasted from react-select docs seems that everything is alright. The error says that you try to render something that is not being able to render (here it says it's some Object).
My bet is this line causes the error:
import Select from 'react-select';
are you sure you properly installed this package?

Try to usw curly brackets arround Select in your import statement:
import {Select} from...
If there are no "default" export defined, you have to use those curly bracets to define the component you want to use.

import * as React from 'react';
import Select from 'react-select';
// Be sure to include styles at some point, probably during your bootstrapping
import 'react-select/dist/react-select.css';
export class Example extends React.Component<any, any> {
var options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
];
function logChange(val) {
console.log("Selected: " + JSON.stringify(val));
}
render() {
return (
<div>
<Select name="form-field-name" value="one" options={options} onChange={logChange}/>
</div>
);
}
}

import React, { Component } from 'react';
import Select from 'react-select';
class App extends Component {
state = {options: [
{
value: '1', label: 'Option 1',
},
{
value: '2', label: 'Option 2',
}
]}
render(){
return (
<div>
<Select
className={"select-item"}
name="option name"
onChange={this.changeHandler}
options={this.state.options}
/>
</div>
)
}
}

Quick answer, this should work:
Demo: https://codesandbox.io/s/stupefied-vaughan-z4mkv?file=/src/Example.tsx
import * as React from "react";
import Select from "react-select";
// Be sure to include styles at some point, probably during your bootstrapping
import "react-select/dist/react-select.css";
var options = [
{ value: "one", label: "One" },
{ value: "two", label: "Two" }
];
function logChange(val) {
console.log("Selected: " + JSON.stringify(val));
}
export default class Example extends React.Component<any, any> {
render() {
return (
<div>
<Select
name="form-field-name"
value="one"
options={options}
onChange={logChange}
/>
</div>
);
}
}
Reason for error:
Either use export default class Example extends React.Component<any, any> {, or in whichever file you are importing and using <Example />, import it as import { Example } from './path/to/file'. Not using the default export specifier or named import in the importing file is causing the error. Read imports / exports in js
Things to do:
Remove var Select = require('react-select');. This is the same as import Select from 'react-select';, just in a different import format (read about ESM and CommonJS to learn more). We should avoid importing components
Use import React from 'react' instead.

Related

How do I include a namespace with a react tsx import?

When I try to import the component 'deleteButton', the compiler claims the class does not exist.
I have tried using an export default, and importing it under an alias.
import React from 'react';
import deleteButton from './Components/deleteButton';
const App: React.FC = () => {
return (
<deleteButton/>
);
}
export default App;
import React from 'react';
import { confirmAlert } from 'react-confirm-alert';
import 'react-confirm-alert/src/react-confirm-alert.css';
export default class deleteButton extends React.Component {
submit = () => {
confirmAlert({
title: 'Confirm to delete',
message: 'Are you sure to delete this file?.',
buttons: [
{
label: 'Yes',
onClick: () => alert('File deleted')
},
{
label: 'No',
onClick: () => alert('Canceled')
}
]
});
};
render() {
return (<div className='container'>
<button onClick={this.submit}>Delete</button>
</div>);
}
}
The expected output should be an HTML Element.
The compiler claims:
Property 'deleteButton' does not exist on type 'JSX.IntrinsicElements'. TS2339
You need to write JSX-Elements upper-case so that react can distinguish between custom elements and build-in ones like span or div. Docs
If you write it lower case, it will look for a native element, which does not exist. So change the name to be upper-case and it will work:
import DeleteButton from './Components/deleteButton';
Hope this helps. Happy coding.

PropTypes.instanceOf of functional component not working

I'm trying for set propTypes of children for a specific type, so when passing children of the wrong type, it throws a warning, but currently, even after saying that children: PropTypes.arrayOf(Option) it gets completely ignored and accepts other types too.
I want SortBy to accept only a list of Option, but it receives native html option without warnings.
Here is the sandbox:
https://codesandbox.io/s/sleepy-currying-fwdlq
And here is the code:
sort-by.js
import React from 'react';
import PropTypes from 'prop-types';
import {Option} from './option';
const SortBy = ({children, onChange}) => (
<select onChange={onChange}>
<Option>---</Option>
{children}
</select>
);
SortBy.Option = Option;
export {
SortBy,
};
SortBy.propTypes = {
onChange: PropTypes.func.isRequired,
children: PropTypes.arrayOf(Option).isRequired,
};
option.js
import React from 'react';
import PropTypes from 'prop-types';
export function Option({ children }) {
return <option>{children}</option>;
}
Option.propTypes = {
children: PropTypes.oneOf(['id', 'state', '---']).isRequired,
};
app.js
import React from 'react';
import {List, Issue, SortBy} from './components';
function App() {
return (
<div>
<SortBy onChange={() => {}}>
<SortBy.Option>
id
</SortBy.Option>
<SortBy.Option>
state
</SortBy.Option>
{/* this one should throw a warning saying that
option is not an instance of Option, but it doesn't */}
<option>---</option>
</SortBy>
<div/>
);
}
export default App;
What I was trying to accomplish is not actually feasible due to:
sophiebits commented on Aug 26, 2015
This would be called elementOfType if we do want it, though I'm not sure we do since if a component is expecting a <Button /> element you should (ideally) be able to pass <PurpleButton /> and have that work too.
https://github.com/facebook/react/pull/4716
But there is a workaround that look like this:
// Validates a singular field
var fieldType = React.PropTypes.shape({
type: React.PropTypes.oneOf([Field])
})
// Accepts either a single field, or an array of fields
// Note: Reject a Form with no children
Form.propTypes = {
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(fieldType), // array of fields
fieldType // singular field
]).isRequired
}
https://github.com/facebook/react/issues/2979#issuecomment-222379916

How Can I Share the Car interface between classes and add Type Checking To CarItem class?

I've made a simple example that highlights a few of the problems / not-understandings I'm having with TypeScript. I created a simple list of cars that reference a caritem detail view. Code is below and also on stackblitz here:
https://stackblitz.com/edit/react-ts-ocjswh
My Questions:
How do I get typechecking to work in CarItem.tsx? I've tried car: Car but that is not correct
What is the proper way to import react and react-dom? I tried import as with no success
I want to share my interface "Car" between index.tsx and CarItem.tsx so if I add another attribute, I don't have to add it to both places. Once I have a large number of interfaces in my project, what is best way to do this?
Index.tsx
import * as React from 'react';
import { render } from 'react-dom';
import CarItem from './CarItem';
interface Car
{
id: number,
model: string
}
interface Cars {
cars: Car[];
}
const App : React.FunctionComponent<Cars> = ({cars}) => {
const myCars = [{
id: 101, model: 'midget'
},{
id:102, model: 'spitfire'
},{
id: 103, model: 'tr6'
}]
return (
<ul>
{myCars.map(function(data){
return (
<CarItem car={data} />
)
}
)}
</ul>
);
}
render(<App />, document.getElementById('root'));
CarItem.tsx
import * as React from 'react';
interface Car
{
id: number,
model: string
}
export default ({car}) => {
return (
<li key={car.id}>...{car.model}</li>
)
}
There was a lot of problem with this code. I refactored it and try to fix it all.
The answers to your questions:
I fixed the type for CarItem
There is nothing wrong with the import, they works. The editor has some syntax highlight problem.
You can export and import the interfaces as well.
Here is the corrected files
index.tsx
import * as React from 'react';
import ReactDOM from 'react-dom';
import CarItem, {Car} from './CarItem';
const App : React.FunctionComponent = () => {
const myCars: Car[] = [{
id: 101, model: 'midget'
},{
id:102, model: 'spitfire'
},{
id: 103, model: 'tr6'
}]
return (
<ul>
{myCars.map(function(data){
return (
<CarItem key={data.id} car={data} />
)
}
)}
</ul>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
CarItem.tsx
import * as React from 'react';
export interface Car
{
id: number,
model: string
}
interface Props {
car: Car;
}
const CarItem: React.FunctionComponent<Props> = ({car}) => {
return (
<li>...{car.model}</li>
)
}
export default CarItem;
And the project: https://stackblitz.com/edit/react-ts-uknhel?file=index.tsx

React-search basic example

I'm trying to get react-search to work in my Meteor app. This is my main App.js in the imports folder:
import Search from 'react-search';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
...
class App extends Component {
...
render() {
let items = [
{ id: 0, value: 'ruby' },
{ id: 1, value: 'javascript' },
{ id: 2, value: 'lua' },
{ id: 3, value: 'go' },
{ id: 4, value: 'julia' }
]
console.log(items)
return (
<div class="">
<Search items={items} />
...
</div>
);
}
}
Once I insert the <Search items={items} /> my app stops working and I get the following console errors:
Any ideas?
I take a look on their source code: https://github.com/StevenIseki/react-search/blob/master/src/Search.js
import React, { Component, PropTypes } from 'react'
React had a break change where PropTypes is no longer inside the react package.
It's in prop-types package now. eg: import PropTypes from 'prop-types'
If you still want to use this package, you have to match the dependency in https://github.com/StevenIseki/react-search/blob/master/package.json
However, the implementation for this package isn't hard. So you highly recommend you create your own component based on their code if needed.
Does this help?

React-Intl How to use FormattedMessage in input placeholder

I'm unsure how to get the values from
<FormattedMessage {...messages.placeholderIntlText} />
into a placeholder format like input:
<input placeholder={<FormattedMessage {...messages.placeholderIntlText} />} />
as it would return [Object object] in the actual placeholder. Is there a way to get the actual correct value?
The <Formatted... /> React components in react-intl are meant to be used in rendering scenarios and are not meant to be used in placeholders, alternate text, etc. They render HTML, not plain text, which is not useful in your scenario.
Instead, react-intl provides a lower level API for exactly this same reason. The rendering components themselves use this API under the hoods to format the values into HTML. Your scenario probably requires you to use the lower level formatMessage(...) API.
You should inject the intl object into your component by using the injectIntl HOC and then just format the message through the API.
Example:
import React from 'react';
import { injectIntl, intlShape } from 'react-intl';
const ChildComponent = ({ intl }) => {
const placeholder = intl.formatMessage({id: 'messageId'});
return(
<input placeholder={placeholder} />
);
}
ChildComponent.propTypes = {
intl: intlShape.isRequired
}
export default injectIntl(ChildComponent);
Please note that I'm using some ES6 features here, so adapt according to your setup.
You can use intl prop from injectIntl HoC
You can also provide function as child component:
<FormattedMessage {...messages.placeholderIntlText}>
{(msg) => (<input placeholder={msg} />)}
</FormattedMessage>
It's july 2019 and react-intl 3 beta is shipped with a useIntl hook to make these kind of translations easier:
import React from 'react';
import {useIntl, FormattedDate} from 'react-intl';
const FunctionComponent: React.FC<{date: number | Date}> = ({date}) => {
const intl = useIntl();
return (
<span title={intl.formatDate(date)}>
<FormattedDate value={date} />
</span>
);
};
export default FunctionComponent;
And then you can make custom hooks to use the methods provided by the API:
import { useIntl } from 'react-intl'
export function useFormatMessage(messageId) {
return useIntl().formatMessage({ id: messageId })
}
For Input placeholder for more details
<FormattedMessage id="yourid" defaultMessage="search">
{placeholder=>
<Input placeholder={placeholder}/>
}
</FormattedMessage>
As from React version >= 16.8, you can use useIntl hook :
import React from 'react';
import { IntlProvider, useIntl } from 'react-intl';
const FunctionComponent = () => {
const intl = useIntl();
const lang = "en";
const messages = {
en: {
'placeholderMessageId': 'placeholder in english',
},
fr: {
'placeholderMessageId': 'placeholder en fançais',
}
}
return (
<IntlProvider locale = {lang} messages = { messages[lang] } >
<input placeholder = { intl.formatMessage({ id: 'placeholderMessageId' })}/>
</IntlProvider >
);
};
export default FunctionComponent;
Based on the react intl wiki the implementation of an input box with translatable placeholder will look like:
import React from 'react';
import { injectIntl, intlShape, defineMessages } from 'react-intl';
const messages = defineMessages({
placeholder: {
id: 'myPlaceholderText',
defaultMessage: '{text} and static text',
},
});
const ComponentWithInput = ({ intl, placeholderText }) => {
return (
<input
placeholder={ intl.formatMessage(messages.placeholder, { text: placeholderText }) }
/>
);
};
ComponentWithInput.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(ComponentWithInput);
and the useage of it:
import ComponentWithInput from './component-with-input';
...
render() {
<ComponentWithInput placeholderText="foo" />
}
...
The id: 'myPlaceholderText', part is necessary to enable the babel-plugin-react-intl to collect the messages for translation.
I would like to suggest this solution :
import { useIntl } from "react-intl";
export default function MyComponent() {
const intl = useIntl();
return (
<input placeholder={intl.formatMessage({ id: "messageId" })} />
);
}
You are trying to render a React component named FormattedMessage into a placeholder tag which is expecting a string.
You should instead just create a function named FormattedMessage that returns a string into the placeholder.
function FormattedMessage(props) {
...
}
<input placeholder=`{$(FormattedMessage({...messages.placeholderIntlText})}` />
Consider this possibility.
The simplest solution
<IntlMessages id="category.name">
{text => (
<Input placeholder={text} />
)}
</IntlMessages>
OR
In my case I had the whole app in one file, so using export wouldn't work. This one uses the normal class structure so you can use the state and other functionality of React if needed.
class nameInputOrig extends React.Component {
render () {
const {formatMessage} = this.props.intl;
return (
<input type="text" placeholder={formatMessage({id:"placeholderIntlText"})} />
);
}
}
const nameInput = injectIntl(nameInputOrig);
Apply using the created constant:
class App extends React.Component {
render () {
<nameInput />
}
}
Starting from the #gazdagerg 's answer, I have adapted his code in order to:
having a new component that is a wrapper over an input
receives an ID of a string from locale conf
based on the ID, it returns the string in respect to the global locale setting
handling the situation when the string ID is not set (this caused exception and page to crash)
import React from 'react';
import { injectIntl, intlShape, defineMessages } from 'react-intl';
const InputWithPlaceholder = ({ intl, placeholder }) => {
const messages = defineMessages({
placeholder: {
id: placeholder,
defaultMessage: '',
},
});
if(messages.placeholder.id) {
return (
<input placeholder={ intl.formatMessage(messages.placeholder) } />
);
} else {
return (
<input/>
);
}
};
InputWithPlaceholder.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(InputWithPlaceholder);
You can use it in other file by:
import the new component
use it with the ID of the locale string as parameter
import InputWithIntlPlaceholder from 'your/path/to/component/InputWithIntlPlaceholder';
... more code here ...
<InputWithIntlPlaceholder placeholder="your.locale.string.id" />
Like this:
import React, {PropTypes} from 'react';
import { injectIntl, FormattedMessage } from 'react-intl';
 
/**
* {
* "hello": "Hello",
* "world": "World"
* }
*/
 
// pure function
const PureFunciton = injectIntl(({ intl }) => {
return (
<div>
<p>{intl.formatMessage({ id: 'hello' })}</p>
<p><FormattedMessage id="world" /></p>
</div>
)
});
 
// class Component
class componentName extends Component {
handleStr = () => {
// return 'Hello';
const { intl } = this.props;
return intl.formatMessage({ id: 'hello' })
}
render() {
return (
<div>
<p>{this.handleStr()}</p>
<p><FormattedMessage id="world" /></p>
</div>
);
}
}
 
export default injectIntl(connect(componentName));

Resources