javascript - 从孩子到父母的反应钩子回调
问题描述
我有这个子组件称为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>
)
}
我希望在选择 aonSelect
时使用从子组件到父组件的回调TodoItem
。但是,每当onSelect
调用时,我的TodoList
重新渲染并且我selectedOptionIndex
的被重置。因此,我的checked
标志只会true
在重置为false
.
如果我删除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>
推荐阅读
- xcode - 函数“UnityGetGLView”的隐式声明在 C99 中无效
- ios - 移动到另一个屏幕时保持 CABasicAnimation 运行
- ffmpeg - 使用偏移量调用时 FFMPEG 失败
- php - PHP密码验证问题
- linux-kernel - 如何防止 Yocto 项目 BadValue 错误?
- rest - 无法创建新的融合页面作为另一个页面的子页面
- javascript - 如何停止可重复的javascript函数
- gradle - 在命令提示符下运行 flutter run 命令时出错:[致命错误] aapt2-3.5.0-5435860.pom:2:1: Content is not allowed in prolog
- amazon-web-services - Spark AWS Glue UI - 错误:无法找到或加载主类 $SPARK_HISTORY_OPTS - Windows Docker
- tensorflow - 如何将 .png 文件转换为 TFrecord tensorflow 格式?