Replies: 6 comments 5 replies
-
Do you have an example? |
Beta Was this translation helpful? Give feedback.
-
import { atom, useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import produce from 'immer';
import React, { useCallback, useEffect, useRef } from 'react'
const initialState = [
{
x: 0,
y: 0
},
{
x: 100,
y: 0
},
{
x: 200,
y: 0
},
]
const state = atom({
key: 'state',
default: initialState
})
const List = () => {
// const data = useRecoilValue(state);
return (
<div>
{
initialState.map((item, i) => {
return(
<ListItem key={i} idx={i}/>
)
})
}
</div>
)
}
const ListItem = ({idx}) => {
const [data, setData] = useRecoilState(state);
const handleOnChange = (e) => {
const copyData = produce(data, (draft) => {
draft[idx].x = Number(e.target.value);
})
setData(copyData);
}
return (
<div>
<input type="number" value={data[idx].x} onChange={handleOnChange} />
</div>
)
}
const Canvas = () => {
// const data = useRecoilValue(state);
return (
<div>
{
initialState.map((item, i) => (
<CanvasItem key={i} idx={i}/>
))
}
</div>
)
}
const CanvasItem = ({idx}) => {
const style = {
position:'absolute',
width: '100px',
height: '100px',
border: '1px solid black',
borderRadius: '50%'
}
const [data, setData] = useRecoilState(state);
const handleDrag = (e) => {
const copyData = produce(data, (draft) => {
draft[idx].x = e.pageX - 50;
draft[idx].y = e.pageY - 50;
})
setData(copyData)
e.preventDefault();
}
return (
<div
style={{left: data[idx].x + 'px', top: data[idx].y + 'px', ...style}}
draggable="true"
onDrag={handleDrag}
onDragOver={(e) => { e.preventDefault() }}>
</div>
)
}
export default () => {
return (
<div>
<List></List>
<Canvas></Canvas>
</div>
)
} |
Beta Was this translation helpful? Give feedback.
-
it looks like this, can avoid brother re-render,but! Required in the child component dynamically creating atom. import { atom, useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import produce from 'immer';
const initialState = [
{
x: 0,
y: 0
},
{
x: 100,
y: 0
},
{
x: 200,
y: 0
},
]
// 在子组件中动态创建atom
const creatStateItem = (id, item) => {
return atom({
key: `state_${id}`,
default: item
})
}
const List = () => {
return (
<div>
{
initialState.map((item, i) => {
return(
<ListItem key={i} id={i} item={item}/>
)
})
}
</div>
)
}
const ListItem = ({id, item}) => {
const [data, setData] = useRecoilState(creatStateItem(id, item));
const handleOnChange = (e) => {
const copyData = produce(data, (draft) => {
draft.x = Number(e.target.value);
})
setData(copyData);
}
return (
<div>
<input type="number" value={data.x} onChange={handleOnChange} />
</div>
)
}
const Canvas = () => {
return (
<div>
{
initialState.map((item, i) => (
<CanvasItem key={i} id={i} item={item}/>
))
}
</div>
)
}
const CanvasItem = ({id, item}) => {
const style = {
position:'absolute',
width: '100px',
height: '100px',
border: '1px solid black',
borderRadius: '50%'
}
const [data, setData] = useRecoilState(creatStateItem(id, item));
const handleDrag = (e) => {
const copyData = produce(data, (draft) => {
draft.x = e.pageX - 50;
draft.y = e.pageY - 50;
})
setData(copyData)
e.preventDefault();
}
return (
<div
style={{left: data.x + 'px', top: data.y + 'px', ...style}}
draggable="true"
onDrag={handleDrag}
onDragOver={(e) => { e.preventDefault() }}>
</div>
)
}
export default () => {
return (
<div>
<List></List>
<Canvas></Canvas>
</div>
)
} |
Beta Was this translation helpful? Give feedback.
-
I want to help, but I don't understand what you are saying and don't have time to read long code. |
Beta Was this translation helpful? Give feedback.
-
this is me actually |
Beta Was this translation helpful? Give feedback.
-
Please note that you should not create atoms or selectors while rendering. Doing so would create a new atom with each render instead of re-using the same shared state with each render. |
Beta Was this translation helpful? Give feedback.
-
The previous state is placed in the parent component.Will the state now be placed in the child components?
Won't it affect child component reuse?
Beta Was this translation helpful? Give feedback.
All reactions