How can I write set name in the circle in upset.js
I have 2 problem.
how to write set name in venndiagram circle?
how to select full areas when i click outside?
Currently when I run my code it looks like this.
but, I want see like this.
const elems = useMemo(
() => [
{ name: "inner", sets: ["S1", "S2"] },
{ name: "left", sets: ["S1"] },
{ name: "right", sets: ["S2"] },
],
[]
);
const [selection, setSelection] = useState<ISetLike<unknown> | unknown[] | null>(null);
const sets = useMemo(() => extractSets(elems), [elems]);
const combinations = useMemo(() => generateCombinations(sets), [sets]);
const select = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setSelection(
Array.from(e.target.closest('div')?.querySelectorAll<HTMLInputElement>('input:checked') ?? []).map(
(d) => d.valueAsNumber
)
);
},
[setSelection]
);
return (
<div>
<VennDiagram
sets={sets}
combinations={combinations}
width={250}
height={150}
selection={selection}
onClick={setSelection}
exportButtons={false}
/>
</div>
);
Related
I'm trying to render some tags from a source and then put it into a buttons in random form but the issue comes after click the button my component re-render for no reason.
why can i do?...
const Blog = () => {
const [articles, setArticles] = useState([]);
const [tags, setTags] = useState([]);
// consult to database
const getData = async () => {
try {
// get aticles, tags
setArticles([
{ name: "title1", id_tag: 1 },
{ name: "title2", id_tag: 2 }
]);
setTags([
{ id: 1, name: "bell" },
{ id: 2, name: "fashion" }
]);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
getData();
}, []);
const getRandomTag = (i) => {
const newTags = tags;
const tag = newTags[Math.floor(Math.random() * newTags.length)];
return (
<button key={i} onClick={() => filterByTag(tag.id)}>
{tag.name}
</button>
);
};
// filter the article by tag
const filterByTag = (id) => {
setArticles(articles.filter((article) => article.id_tag === id));
};
return (
<>
<ul>
{articles.map((article, i) => (
<li key={i}>{article.name}</li>
))}
</ul>
<h4>TAGS</h4>
<ul>{tags.map((tag, i) => getRandomTag(i))}</ul>
</>
);
export default Blog;
https://codesandbox.io/s/heuristic-solomon-sp640j?from-embed=&file=/src/Blog.js
That's because your component re-renders whenever any state inside it or any props it receives changes either by value or reference. And whenever you map something without caching its value it maps on each rerender. You have tu either split it into other component or use caching.
import { useCallback, useEffect, useMemo, useState } from "react";
const Blog = () => {
const [articles, setArticles] = useState([]);
const [tags, setTags] = useState([]);
// consult to database
const getData = async () => {
try {
// get aticles, tags
setArticles([
{ name: "title1", id_tag: 1 },
{ name: "title2", id_tag: 2 },
{ name: "title3", id_tag: 3 },
{ name: "title4", id_tag: 4 },
{ name: "title5", id_tag: 5 },
{ name: "title6", id_tag: 6 }
]);
setTags([
{ id: 1, name: "bell" },
{ id: 2, name: "fashion" },
{ id: 3, name: "fancy" },
{ id: 4, name: "tag" },
{ id: 6, name: "name" },
]);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
getData();
}, []);
const filterByTag = useCallback((id) => {
setArticles(currentArticles => currentArticles.filter((article) => article.id_tag === id));
}, [setArticles]);
const getRandomTag = useCallback(
(i) => {
const newTags = tags;
const tag = newTags[Math.floor(Math.random() * newTags.length)];
return (
<button key={i} onClick={() => filterByTag(tag.id)}>
{tag.name}
</button>
);
},
[tags, filterByTag]
);
// filter the article by tag
const renderTags = useMemo(() => {
return tags.map((tag, i) => getRandomTag(i));
}, [tags, getRandomTag]);
return (
<>
<ul>
{articles.map((article, i) => (
<li key={i}>{article.name}</li>
))}
</ul>
<h4>TAGS</h4>
<ul>{renderTags}</ul>
</>
);
};
export default Blog;
Here you have a working example of caching https://codesandbox.io/s/sad-shadow-8pogoc?file=/src/Blog.js
I have this dynamic checkbox, that I want to update the state with the selected options only ,I tried to add some checks to filter the state on change , but it seems I am not seeing what went wrong!
const checkBoxesOptions = [
{ id: 1, title: 'serviceOne' },
{ id: 2, title: 'serviceTwo' },
{ id: 3, title: 'serviceThree' },
];
const [selectedCheckBoxes, setSelectedCheckBoxes] = React.useState([]);
{checkBoxesOptions.map((checkBox, i) => (
<CheckBox
key={i}
label={checkBox.title}
value={1}
checked={false}
onChange={value => {
let p = {
title: checkBox.title,
isTrue: value,
};
if (p.isTrue) {
const tempstate = selectedCheckBoxes.filter(
checkbox => checkbox !== checkBox.title
);
console.log('temp state', tempstate);
setSelectedCheckBoxes([...selectedCheckBoxes, p.title]);
}
console.log(p);
}}
/>
))}
The value parameter is the event object.
(event) => {
const value = event.target.checked
<... Rest of the code ...>
}
I thinking for few days but cant realize how can i make it. I have 4 json data and 4 picker.
Its for city,district,village,neirborhood. In first i must choose city then in second picker it must show district about that i choose city. When i choose district from picker third one must show villages about that district. And neirborhood is same too. In that json datas they have some connection. Like city json have ' id-name' district have 'id-cityid-name' village have 'id-districtid-name' neirborhood have 'id-villageid-name' Like that. But i cant figure out how can i make it. Its my codes I really stuck with that hardly i need some help please. Thank you! My codes :
Elements :
const DropdownElements = [
{
key: 1,
title: "Şehir",
placeholder: "Şehir Seçiniz",
apiUrl: "https://api.npoint.io/995de746afde6410e3bd",
type: "city",
selecteditem: "",
data : [],
},
{
key: 2,
title: "İlçe",
placeholder: "İlçe Seçiniz",
apiUrl: "https://api.npoint.io/fc801dbd3fc23c2c1679",
type: "district",
selecteditem: "",
data : [],
},
{
key: 3,
title: "Köy",
placeholder: "Köy Seçiniz",
apiUrl: "https://api.npoint.io/72cf025083b70615b8bb",
type: "village",
selecteditem: "",
data : [],
},
{
key: 4,
title: 'Mahalle',
placeholder:'Mahalle Seçiniz',
apiUrl: 'https://api.npoint.io/0c04c63923c8ca4e117b',
type: 'neighborhood',
selecteditem: "",
data : [],
},
];
Component :
const PickerCompanent = (props) => {
const [xdata, setData] = useState([]);
const [newData, setNewData] = useState([]);
let x;
let y = [];
// data.filter((a) => a.il_id == "3");
useEffect(() => {
props.datasource.then(setData);
switch (props.type) {
case "city":
x = props.selecteditem;
setNewData(xdata);
break;
case "district":
y = xdata.filter((element) => {
if (props.selecteditem === element.id) {
return element;
}
});
break;
case "village":
console.log("village");
break;
default:
console.log("def");
break;
}
}, [props.datasource]);
return (
<Select
showSearch
style={{ width: 200, marginLeft: 15 }}
placeholder={props.placeholder}
optionFilterProp="children"
onChange={(x) => props.onChange(x)}
onFocus={props.onFocus()}
datasource={xdata}
onSearch={props.onSearch()}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{xdata &&
xdata.map((x) => {
return (
<Select.Option key={x.id} value={x.id}>
{x.name}{" "}
</Select.Option>
);
})}
</Select>
);
};
My App :
const App = () => {
const [dataap, setDataAp] = useState([]);
const [idhold, setIDHold] = useState();
const filldata = (value) => {};
function onChange(value) {
setIDHold(value);
console.log(value);
}
const getData = (value, type) => {
return fetch(value)
.then((x) => x.json())
.then((y) => {
return y;
});
};
function onFocus() {}
function onSearch(val) {}
return (
<Space>
{DropdownElements.map((x) => {
return (
<PickerCompanent
showSearch
selecteditem={idhold}
key={x.key}
placeholder={x.placeholder}
type={x.type}
datasource={getData(x.apiUrl)}
onFocus={onFocus}
onChange={(z) => onChange(z)}
onFocus={onFocus}
onSearch={onSearch}
></PickerCompanent>
);
})}
</Space>
);
};
If you need i can give my teamviewer or skype too. I really need that help thanks for replies!
Sandbox : codesandbox.io/s/runtime-monad-vxit
https://codesandbox.io/s/mystifying-moore-7w105?file=/src/App.js
Select CityTwo to see the dropdown update.
You need a switch. Updating arrays inside state is tricky. You can't populate or push anything in an array that's in state. Update your array outside state, THEN update state.
I am using Ant Design for my React project and I'm having trouble with the Table component. I have a list of tasks to which I add a new task based on a Form content - currently just by adding to an array of objects (taskListMock in the code snippets), the app is not linked to any backend. The form works fine, however, the Table does not refresh, even though the dataSource prop of the Table gets its content directly from the state and the state updates correctly - confirmed by logging and devtools. Curiously, the table refreshes with the new task when I initiate the implemented sorting, so my suspicion is that the Table somehow does not refresh its content from the state change, only on onChange hooks or something, but I'm feeling in a bit of a dead-end - any help would be greatly appreciated since I'm planning to use similar functionality in other Tables.
The structure is pretty simple, I have a TasksIndex.js with the Table as an individual component in TaskListTable.js
TaskListTable.js:
const TaskListTable = (props) => {
const { t } = useTranslation();
const [tableContent, setTableContent] = useState(props.tasks);
return (
<React.Fragment>
<Table
pagination={false}
dataSource={tableContent}
columns={[
{
title: t("tasks.name"),
key: "name",
render: (text) => {
return <p>{text.slug}</p>;
},
},
{
title: t("tasks.dateDue"),
dataIndex: "dateDue",
key: "dateDue",
sorter: (a, b) =>
new Date(a.dateDue).getTime() - new Date(b.dateDue).getTime(),
render: (dateDue) => {
let dateFormatted = moment(dateDue);
return <>{dateFormatted.format("LL")}</>;
},
defaultSortOrder: "ascend",
},
{
title: t("tasks.priority"),
key: "priority",
dataIndex: "priority",
render: (priority) => (
<React.Fragment>
{priority === "low" ? (
<Tag color="geekblue">{t("tasks.lowPriority")}</Tag>
) : (
""
)}
{priority === "normal" ? (
<Tag color="green">{t("tasks.normalPriority")}</Tag>
) : (
""
)}
{priority === "high" ? (
<Tag color="volcano">{t("tasks.highPriority")}</Tag>
) : (
""
)}
</React.Fragment>
),
sorter: (a, b) => {
const priorityOrder = ["low", "normal", "high"];
return (
priorityOrder.indexOf(a.priority) -
priorityOrder.indexOf(b.priority)
);
},
},
{
title: t("tasks.options"),
key: "options",
render: (item) => {
return (
<Checkbox value={item.id}>{t("tasks.setCompleted")}</Checkbox>
);
},
},
]}
></Table>
</React.Fragment>
);
};
export default TaskListTable;
TaskIndex.js:
const TasksIndex = () => {
const [isModalOpen, setModalOpen] = useState(false);
const [taskList, updateTaskList] = useState(taskListMock);
const [form] = Form.useForm();
const addTask = useCallback(
(values) => {
const newTaskList = taskList;
newTaskList.push({
id: taskList[taskList.length - 1] + 1,
slug: values.name,
description: values.description,
dateDue: values.dateDue.format("YYYY-MM-DD"),
priority: values.priority,
checked: false,
});
form.resetFields();
updateTaskList(newTaskList);
closeModal();
},
[taskList, form]
);
const openModal = () => {
setModalOpen(true);
};
const closeModal = () => {
setModalOpen(false);
};
const { t } = useTranslation();
return (
<React.Fragment>
<Title>{t("tasks.tasksOverviewHeader")}</Title>
<Row gutter={[16, 24]}>
<Col className="gutter-row" span={24}>
<TaskListTable tasks={taskList}></TaskListTable>
</Col>
</Row>
...
...
I finally fixed it - it seems that creating a new array and pushing the new task to it was not considered a state change (or perhaps a Table change trigger), unlike using the spread operator. The working code looks like this:
const addTask = (values) => {
const newTask = {
id: taskList[taskList.length - 1] + 1,
slug: values.name,
description: values.description,
dateDue: values.dateDue.format("YYYY-MM-DD"),
priority: values.priority,
checked: false,
};
updateTaskList([...taskList, newTask]);
closeModal();
form.resetFields();
};
So I have the below code which I would like to refactor, so I will not have to repeat it again and again.
I made a function saveQuestion but it solves half the problem. I do not have to call
setDeleteFilters(true); setFiltersAreApplied(true); again...
But is there a way to call the saveQuestion function each time with a different hook like once with setAlfaIsTrue(newValue); then with setBetaIsTrue(newValue); etc ?
The main problem I think is the dependencies...
Thank you :)
const saveQuestion = useCallback(
() => {
setDeleteFilters(true);
setFiltersAreApplied(true);
},
[ deleteFilters, filtersAreApplied ]
);
const saveAlfa = useCallback(
(newValue) => {
setAlfaIsTrue(newValue);
saveQuestion();
// setDeleteFilters(true);
// setFiltersAreApplied(true);
},
[ alfaIsTrue ]
);
const saveBeta = useCallback(
(newValue) => {
setBetaIsTrue(newValue);
saveQuestion();
// setDeleteFilters(true);
// setFiltersAreApplied(true);
},
[ betaIsTrue ]
);
I got exactly what I wanted from T.J.Crowder
and this is how the code looks now.
Nice and concise.
const [ saveAlfa, saveBeta, saveGamma, saveDelta ] = [
setAlfaIsTrue,
setBetaIsTrue,
setGammaIsTrue,
setDeltaIsTrue
].map((fn, flag) =>
useCallback((newValue) => {
fn(newValue);
setDeleteFilters(true);
setFiltersAreApplied(true);
}, [flag])
);
thank you
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Here is all the code:
I still need to correct the dependencies...
const AnswerSwitch = (props) => {
return (
<View style={styles.multipleChoiceContainer}>
{/* <Text style={{color:Colours.moccasin_light}} >{props.label}</Text> */}
<BoldText>{props.label}</BoldText>
<View style={{ marginHorizontal: 10 }}>
<Switch
style={{ transform: [ { scaleX: 1 }, { scaleY: 0.7 } ] }}
thumbColor={Platform.OS === 'android' ? Colours.maroon : ''}
trackColor={Platform.OS === 'android' ? Colours.moccasin_light : ''}
value={props.state}
onValueChange={props.onChange}
disabled={props.disabled}
/>
</View>
</View>
);
};
////////////////////////////////////////////////////////
const DifficultyLevelSettingsScreen = (props) => {
const { width, height } = Dimensions.get('window');
const widthMultiplier = DimensionsForStyle.widthMultiplier;
const textMultiplier = DimensionsForStyle.textMultiplier;
const cardHeight = DimensionsForStyle.cardHeight;
const cardWidth = DimensionsForStyle.cardWidth;
const dispatch = useDispatch();
const [ isLoading, setIsLoading ] = useState(false);
// For the switches
// They run when a switch is touched
const [ alfaIsTrue, setAlfaIsTrue ] = useState(true);
const [ betaIsTrue, setBetaIsTrue ] = useState(true);
const [ gammaIsTrue, setGammaIsTrue ] = useState(true);
const [ deltaIsTrue, setDeltaIsTrue ] = useState(true);
// For checking if we have filters on the server so we set their state from there...
const [ filtersAreApplied, setFiltersAreApplied ] = useState(false);
// Gets updated everytime we set a filter, so we delete their previous state
const [ deleteFilters, setDeleteFilters ] = useState(false);
// Get state of filters from redux to update them
// const savedFilters = useSelector((state) => state.questions.filters);
const loadFilters = useCallback(
async () => {
const userFilters = await AsyncStorage.getItem('userFilters');
const savedFilters = JSON.parse(userFilters);
let applySavedFilters = false;
for (const key in savedFilters) {
applySavedFilters = savedFilters[key].filtersAreApplied;
// If we have savedFilters and we didn't press a switch then...
if (applySavedFilters && !deleteFilters) {
setAlfaIsTrue(savedFilters[key].alfa);
setBetaIsTrue(savedFilters[key].beta);
setGammaIsTrue(savedFilters[key].gamma);
setDeltaIsTrue(savedFilters[key].delta);
// setFiltersAreApplied(false)
}
}
// Get state of filters to send them to server
const appliedFilters = {
alfa: alfaIsTrue,
beta: betaIsTrue,
gamma: gammaIsTrue,
delta: deltaIsTrue,
filtersAreApplied: filtersAreApplied
};
// If a switch is touched then 'deleteFilters' will be true.
if (deleteFilters || savedFilters.filtersAreApplied) {
await dispatch(questionsActions.deletePreviousFilters());
await dispatch(questionsActions.setFilters(appliedFilters));
}
// Fetch them again to update the "initial" state of filters...
// dispatch(questionsActions.fetchFilters());
},
[ alfaIsTrue, betaIsTrue, gammaIsTrue, deltaIsTrue, deleteFilters, filtersAreApplied, dispatch ]
);
// loadFilters after focusing
useEffect(
() => {
const willFocusEvent = props.navigation.addListener('willFocus', loadFilters);
return () => willFocusEvent.remove();
},
[ loadFilters ]
);
// loadFilters initially...
useEffect(
() => {
setIsLoading(true);
loadFilters().then(() => setIsLoading(false));
},
[ loadFilters ]
);
// For setting the email on the HeaderTitle
useEffect(
() => {
const getData = async () => {
// Note: getItem is asynchronous, so we get a promise
await dispatch(questionsActions.fetchAllUsersData());
const userData = await AsyncStorage.getItem('userData');
if (userData) {
// parse converts a string to an object or array
const transformedData = JSON.parse(userData);
const { userEmail } = transformedData;
props.navigation.setParams({ userEmail: userEmail });
}
};
getData();
},
[ dispatch ]
);
const saveQuestion = useCallback(
() => {
// So filters on server will not be deleted
// when you open the DifficultyLevelSettingsScreen, unless you make a change.
setDeleteFilters(true);
setFiltersAreApplied(true);
},
[ deleteFilters, filtersAreApplied ]
);
// These actions run when the according switch is touched...
const saveAlfa = useCallback(
(newValue) => {
setAlfaIsTrue(newValue);
saveQuestion()
},
[ alfaIsTrue ]
);
const saveBeta = useCallback(
(newValue) => {
setBetaIsTrue(newValue);
saveQuestion()
},
[ betaIsTrue ]
);
const saveGamma = useCallback(
(newValue) => {
setGammaIsTrue(newValue);
saveQuestion()
},
[ gammaIsTrue ]
);
const saveDelta = useCallback(
(newValue) => {
setDeltaIsTrue(newValue);
saveQuestion()
},
[ deltaIsTrue ]
);
return (
// <CustomLinearGradient>
<ScrollView style={styles.screen}>
<View style={styles.difficultyLevelStyle}>
{isLoading ? (
<ActivityIndicator size="small" color={Colours.maroon} />
) : (
<BoldText style={styles.title}>Επιλογή βαθμού (ή βαθμών) δυσκολίας</BoldText>
)}
<View style={styles.switchesSummary}>
<AnswerSwitch
state={alfaIsTrue}
// onChange={(newValue) => setAlfaIsTrue(newValue)}
onChange={saveAlfa}
label="Επίπεδο: Α"
// disabled={betaIsTrue || gammaIsTrue || deltaIsTrue}
/>
<AnswerSwitch
state={betaIsTrue}
// onChange={(newValue) => setBetaIsTrue(newValue)}
onChange={saveBeta}
label="Επίπεδο: Β"
// disabled={alfaIsTrue || gammaIsTrue || deltaIsTrue}
/>
<AnswerSwitch
state={gammaIsTrue}
// onChange={(newValue) => setGammaIsTrue(newValue)}
onChange={saveGamma}
label="Επίπεδο: Γ"
// disabled={alfaIsTrue || betaIsTrue || deltaIsTrue}
/>
<AnswerSwitch
state={deltaIsTrue}
// onChange={(newValue) => setDeltaIsTrue(newValue)}
onChange={saveDelta}
label="Επίπεδο: Δ"
// disabled={alfaIsTrue || betaIsTrue || gammaIsTrue}
/>
<Line />
</View>
</View>
</ScrollView>
// </CustomLinearGradient>
);
};
DifficultyLevelSettingsScreen.navigationOptions = ({ navigation }) => {
return {
headerTitle: navigation.getParam('userEmail'),
headerLeft: (
<HeaderButtons HeaderButtonComponent={CustomHeaderButton}>
<Item
title="menu"
iconName={Platform.OS === 'android' ? 'md-menu' : 'ios-menu'}
onPress={() => navigation.toggleDrawer()}
/>
</HeaderButtons>
)
};
};
There is also an other file with 10 switches...
This custom hook will do the trick
const useSaveQuestion = (saveFunc, deps) =>
useCallback(
newValue => {
saveFunc(newValue);
setDeleteFilters(true);
setFiltersAreApplied(true);
},
[deleteFilters, filtersAreApplied, ...deps],
);
And this is how you use it:
const saveAlfa = useSaveQuestion(
newValue => {
setAlfaIsTrue(newValue);
saveQuestion();
},
[alfaIsTrue],
);
const saveBeta = useSaveQuestion(
newValue => {
setBetaIsTrue(newValue);
saveQuestion();
},
[betaIsTrue],
);