javascript - 从子级到父级的 React hook 回调

标签 javascript reactjs react-hooks

我有一个名为 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>

关于javascript - 从子级到父级的 React hook 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58042471/

相关文章:

javascript重复更改文档背景颜色

javascript - 加密.js : "Uint8ClampedArray" is undefined in IE 11

reactjs - 无法在React中执行react状态

javascript - 如何从另一个表单组件更新书籍列表?

javascript - 我如何更改 woocommerce 中产品默认下拉排序的样式

javascript - 在 Internet Explorer 中以 Quirks 模式加载页面 - doctype 已注释掉

javascript - 如何在没有嵌套导航的情况下进行导航

javascript - 如何使用 react 路由器通过永久链接引用数据

reactjs - 创建 react 应用程序和元数据

javascript - 带有 useState 钩子(Hook)的 React 功能组件立即执行函数