从子级到父级的 React 钩子回调



我有一个名为TodoList的子组件

const TodoItem = ({ checked, children }) => 
(<TouchableOpacity 
style={{ backgroundColor: checked && 'red'}}>
{children}
</TouchableOpacity>
);
const TodoList = props => {
const {
options = [],
onSelect,
...rest
} = props;
const [selectedOptionIndex, setSelectedOptionIndex] = useState(null);
useEffect(() => {
onSelect(options[selectedOptionIndex]);
}, [onSelect, options, selectedOptionIndex]);
const renderItem = (o, index) => {
return (
<TodoItem
key={o + index}
onPress={() => setSelectedOptionIndex(index)}
checked={index === selectedOptionIndex}>
{index === selectedOptionIndex && <Tick />}
<Text>{o}</Text>
</TodoItem>
);
};
return (
<View {...rest}>{options.map(renderItem)}</View>
);
};
export default TodoList;

我有一个名为Container的父组件

export default function() {
const [item, setItem] = setState(null);
return (
<Screen>
<TodoList options={[1,2,3]} onSelect={(i) => setItem(i)} />
</Screen>
)
}

每当选择TodoItem时,我都想使用onSelect从子组件回调到父组件。但是,每当调用onSelect时,我的TodoList都会重新渲染,我的selectedOptionIndex会重置。因此,我的checked标志只会在重置为false之前短暂更改为true

如果我删除onSelect回调,它可以正常工作。但我需要为孩子和父母setState。我该怎么做?

很难说为什么会发生这种情况,很可能是因为容器的状态正在发生变化,导致所有内容重新渲染。

不过,这样的事情应该可以帮助您。

const { render } = ReactDOM;
const { useEffect, useState } = React;
const ToDoItem = ({checked, label, onChange, style}) => {
const handleChange = event => onChange(event);
return (
<div style={style}>
<input type="checkbox" checked={checked} onChange={handleChange}/>
{label}
</div>
);
}
const ToDoList = ({items, onChosen}) => {
const [selected, setSelected] = useState([]);

const handleChange = item => event => {
let s = [...selected];
s.includes(item) ? s.splice(s.indexOf(item), 1) : s.push(item);
setSelected(s);
onChosen(s);
}

return (
<div>
{items && items.map(i => {
let s = selected.includes(i);
return (
<ToDoItem 
key={i} 
label={i} 
onChange={handleChange(i)} 
checked={s}
style={{textDecoration: s ? 'line-through' : ''}}/>
)
})}
</div>
);
}
const App = () => {
const [chosen, setChosen] = useState();
const handleChosen = choices => {
setChosen(choices);
}
return (
<div>
<ToDoList items={["Rock", "Paper", "Scissors"]} onChosen={handleChosen} />
{chosen && chosen.length > 0 && <pre>Chosen: {JSON.stringify(chosen,null,2)}</pre>}
</div>
);
}
render(<App />, document.body)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>

原来我的顶级组件Screen导致这种重新渲染。在我的Screen功能组件中,我在return之前有这段代码

const Content = scroll
? contentProps => {
const { style: contentContainerStyle } = contentProps;
return (
<ScrollView {...contentContainerStyle}>
{contentProps.children}
</ScrollView>
);
}
: View;
return (
<Content>{children}</Content>
)

它以某种方式(不知道为什么(导致孩子们每次我的状态改变时重新渲染。 我通过删除函数来修复它,并让它简单地返回一个View

const Content = scroll ? ScrollView : View;

相关内容

  • 没有找到相关文章

最新更新