Type 'null' is not assignable to type 'SetStateAction<Date>' - react-datepicker

After I have checked other answers, here is the one that completely works for me:
() => {
const [startDate, setStartDate] = useState<Date|null>(new Date());
return (
<DatePicker selected={startDate} onChange={(date: Date | null) => setStartDate(date)} />
);
};

Related

Set a form value using react-hook-form within React-Admin

In my React-Admin app, I'd like to leverage react-hook-form's useFormContext for various things, such as, for example, setting the default pre-selected choice in this custom input field:
...
import {
Create, SimpleForm, SelectInput
} from 'react-admin';
import { useFormContext } from 'react-hook-form';
const MyInput = () => {
const formContext = useFormContext();
formContext.setValue('category', 'tech');
return (
<SelectInput source="category" choices={[
{ id: 'tech', name: 'Tech' },
{ id: 'people', name: 'People' },
]}
/>
);
};
...
const ItemCreate = () => {
return (
<Create>
<SimpleForm>
<MyInput />
</SimpleForm>
</Create>
);
};
...
This sets the pre-selected value of the field, just as intended. But it throws a warning: Cannot update a component ("Form") while rendering a different component ("MyInput")...
Is there some way to achieve this without getting the warning?
Note: The only reason I'm using a custom input field here is because when I put useFormContext() directly into the component that contains SimpleForm it returns null (similarly described here).
The warning is related to the fact that the entire body of the MyInput() function is executed during each render, you need to call the setValue() function inside the useEffect hook.
Got this working by moving formContext.setValue into a useEffect hook:
...
import {
Create, SimpleForm, SelectInput
} from 'react-admin';
import { useFormContext } from 'react-hook-form';
const MyInput = () => {
const formContext = useFormContext();
// moved the setValue into a useEffect
useEffect(() => {
formContext.setValue('category', 'tech');
});
return (
<SelectInput source="category" choices={[
{ id: 'tech', name: 'Tech' },
{ id: 'people', name: 'People' },
]}
/>
);
};
...
const ItemCreate = () => {
return (
<Create>
<SimpleForm>
<MyInput />
</SimpleForm>
</Create>
);
};
...

Unable to open URL: maps:0,0?q=XX,XX

I got a lot of these errors in production: "Unable to open URL: maps:0,0?q=XX,XX". All are from iOS v16.x, on different devices.
My links are created this way:
const MapLink = ({ coords, label, style, type = 'tDF' }: Props) => {
const { theme } = useTheme();
const [can, setCan] = useState<boolean>();
const url = useMemo(
() =>
coords
? `${Platform.select({
ios: 'maps',
android: 'geo',
})}:0,0?q=${coords.latitude},${coords.longitude}`
: '',
[coords],
);
useEffect(() => {
coords
? Linking.canOpenURL(url)
.then(r => setCan(r))
.catch(() => setCan(false))
: setCan(false);
}, [coords]);
return can && coords && coords.latitude && coords.longitude ? (
<Button
bgColor={theme.color.textL}
type={'underline'}
size={'sm'}
label={label ?? ''}
onPress={() => Linking.openURL(url).then()}
style={style}
/>
) : label ? (
<Typo type={type} text={label} color={theme.color.text} />
) : null;
};
I can't reproduce it neither on Simulator, neither on a real device.
Before activate the link, I check with canOpenURL, so I don't understand how it's possibile that 1) A simple map link is not openable 2) canOpenURL should return true to activate the link, so why the error then?
Try this:
<View>
{
can && coords && coords.latitude && coords.longitude ? (
<Button
bgColor={theme.color.textL}
type={'underline'}
size={'sm'}
label={label ?? ''}
onPress={() => Linking.openURL(url).then()}
style={style}
/>
) :label ? (
<Typo type={type} text={label} color={theme.color.text} />
) :null
}
</View>

How to dynamically dispatch and wait for promises

How do i dispatch a dynamically determined amount of times through redux?
I have users who are able to create lists of items and create as many as they like. When they navigate to an item page they can choose which lists to add it to.
This means that i may have to dispatch adding an item to one list OR MORE.
I want to dispatch the action to receive my updated lists only if all dispatches to 'add an item' to a list return a promise.
If i iterate through an array and pass in an argument to dispatch with is there a way to wait on a promise before continuing to the next step/array-index?
eg i'd need to call something like this several times but how many times will be determined by user and should only
export const addToList = (user_id, list_id, stock_ticker) => dispatch => {
return StockApiutil.addToList(user_id, list_id, stock_ticker)
.then(lists => dispatch(receiveLists(lists)))
};
export const addToAllLists = (user_id, list_ids, stock_ticker) => dispatch => {
dispatch(startListLoading());
list_ids.map( list_id =>
addToList(user_id, list_id, stock_ticker)
)
.then(dispatch(stopListLoading()))
}
This doesn't work because it doesn't return a promise and if i use a promise.all i won't create an array corresponding to final state for the lists.
You can do the following:
export const addToList = (
user_id,
list_id,
stock_ticker
) => (dispatch) => {
//you are returning a promise here, that is good
return StockApiutil.addToList(
user_id,
list_id,
stock_ticker
).then((lists) => dispatch(receiveLists(lists)));
};
export const addToAllLists = (
user_id,
list_ids,
stock_ticker
) => (dispatch) => {
dispatch(startListLoading());
//return a single promise using Promise.all
return Promise.all(
list_ids.map((list_id) =>
//also add (dispatch) so you actually call the thunk
addToList(user_id, list_id, stock_ticker)(dispatch)
)
).then(()=>dispatch(stopListLoading()));
};
There was a syntax error in the last line, should have been .then(()=>dispatch(stopListLoading())); looking at your parameter names I can see you are not used to write JS code as it's easy to spot if you run it, below is a working example:
const { Provider, useDispatch } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
//actions
const later = (...args) =>
new Promise((r) => setTimeout(() => r(args), 100));
const StockApiutil = {
addToList: (a, b, c) => later(a, b, c),
};
const receiveLists = (list) => ({
type: 'recieveList',
payload: list,
});
const startListLoading = (payload) => ({
type: 'startListLoading',
payload,
});
const stopListLoading = (payload) => ({
type: 'stopListLoading',
payload,
});
const addToList = (user_id, list_id, stock_ticker) => (
dispatch
) => {
return StockApiutil.addToList(
user_id,
list_id,
stock_ticker
).then((lists) => dispatch(receiveLists(lists)));
};
const addToAllLists = (user_id, list_ids, stock_ticker) => (
dispatch
) => {
dispatch(startListLoading());
//return a single promise using Promise.all
return Promise.all(
list_ids.map((list_id) =>
//also add (dispatch) so you actually call the thunk
addToList(user_id, list_id, stock_ticker)(dispatch)
)
).then(() => dispatch(stopListLoading()));
};
const reducer = (state, { type, payload }) => {
console.log('in reducer:', type, payload);
return state;
};
//creating store with redux dev tools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
{},
composeEnhancers(
applyMiddleware(
({ dispatch, getState }) => (next) => (action) =>
//simple thunk implementation
typeof action === 'function'
? action(dispatch, getState)
: next(action)
)
)
);
const App = () => {
const dispatch = useDispatch();
React.useEffect(
() =>
dispatch(
addToAllLists(
'user id',
[1, 2, 3, 4, 5],
'stock ticker'
)
),
[dispatch]
);
return 'check the console';
};
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="root"></div>

Yii2 - input search with auto-complete

I am using default Yii2 library for auto-complete. How can I make it, so it is reading values from DB while user is typing?
This is code I have so far, but query is done when the page is created:
echo AutoComplete::widget([
'name' => 'tradeName',
'model' => TradeNames::find()->select('name')->all(),
'options' => [
'class' => 'form-control'
],
'clientOptions' => [
'source' => array_column(TradeNames::find()->select('name')->asArray()->all(), 'name'),
},
],
]);
I followed this advice
jqueryui.com/autocomplete/#multiple and have written next code
<div id="autocomplete" class="ui-widget">
<?= \yii\jui\AutoComplete::widget([
'attribute' => 'attribute',
'name' => 'tradeName',
'clientOptions' => [
'source' => \Yii::$container->get('JsExpression',['function(request, response) {
response( $.ui.autocomplete.filter( window.dataAsArray, extractLast( request.term ) ) );
}']),
'select' => \Yii::$container->get('JsExpression',['function(event, ui) {
var terms = split( this.value );
terms.pop();
terms.push( ui.item.value );
terms.push( "" );
this.value = terms.join( ", " );
return false;
}']),
'focus' => \Yii::$container->get('JsExpression',['function() {
return false;
}']),
]
]) ?>
</div>
<script>
window.dataAsArray = ['item1', 'item2', 'item3'];
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$(document).ready( function() {
$('#autocomplete').on('keydown', function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB && $( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
});
});
</script>
maybe it help to someone
try this
use yii\jui\AutoComplete;
use yii\web\JsExpression;
<?php
$data = TradeNames::find()
->select(['name as value', 'name as label','id as id'])
->asArray()
->all();
echo 'Trade Names' .'<br>';
echo AutoComplete::widget([
'name' => 'tradeName',
'id' => 'trade_name',
'clientOptions' => [
'source' => $data,
// 'minLength'=>'3',
'autoFill'=>true,
'select' => new JsExpression("function( event, ui ) {
$('#memberssearch-family_name_id').val(ui.item.id);//#memberssearch-family_name_id is the id of hiddenInput.
}")],
]);
?>
<?= Html::activeHiddenInput($model, 'tradeName')?>

Creating a boolean form widget that accepts null value

My Symfony model has a field which is boolean but also accepts NULL so effectively is a tri-state value.
How can I write a widget for this? Symfony auto-generates a sfWidgetFormCheckbox but that
can not be set to NULL.
I tried a sfWidgetFormChoice with but I had to specify the values as strings to get them work:
$this->setWidget('wt', new sfWidgetFormChoice(array(
'choices' => array(true => 'true', false => 'false', null => 'null')
)));
It works for storing values but whenever I save a "false" value, the select jumps back to 'null'. I tried several combinations of 'false', '0', '' etc. but got nothing to work in all three cases.
Any ideas?
An example right from the docs:
class sfWidgetFormTrilean extends sfWidgetForm
{
public function configure($options = array(), $attributes = array())
{
$this->addOption('choices', array(
0 => 'No',
1 => 'Yes',
'null' => 'Null'
));
}
public function render($name, $value = null, $attributes = array(), $errors = array())
{
$value = $value === null ? 'null' : $value;
$options = array();
foreach ($this->getOption('choices') as $key => $option)
{
$attributes = array('value' => self::escapeOnce($key));
if ($key == $value)
{
$attributes['selected'] = 'selected';
}
$options[] = $this->renderContentTag(
'option',
self::escapeOnce($option),
$attributes
);
}
return $this->renderContentTag(
'select',
"\n".implode("\n", $options)."\n",
array_merge(array('name' => $name), $attributes
));
}
}

Resources