子组件调用父组件
- 使用 props 数据流(单向向下)
const Parent = () => {
const [state, setState] = useState(0)
return <Child update={setState} />
}
const Child = ({ update }) => (
<button onClick={() => update(233)}>update</button>
)
- 使用 Context
const Context = React.createContext()
const Parent = () => {
const [state, setState] = useState(0)
return (
<Context.Provider value={{ update: setState }}>
<Child />
</Context.Provider>
)
}
const Child = () => (
<Context.Consumer>
{({ update }) => <button onClick={() => update(233)}>update</button>}
</Context.Consumer>
)
或者
const Context = React.createContext()
const Parent = () => {
const [state, setState] = useState(0)
const context = useContext(Context)
context.update = setState
return <Child />
}
const Child = () => {
const { update } = useContext(Context)
return <button onClick={() => update(233)}>update</button>
}
父组件调用子组件
使用 ref
const Parent = () => {
const ref = useRef()
useEffect(() => {
ref.current.update(233)
})
return <Child ref={ref} />
}
const Child = React.forward((props, ref) => {
const [state, setState] = useState(0)
useImperativeHandle(ref, () => ({
update: setState
}))
return <p>{state}</p>
})
兄弟组件通信
由于 React 单向数据流的特点,所以数据只能从上向下传递。所以组件需要调用父组件 setState,来发布新的数据流向兄弟组件。
const Parent = () => {
const [state, setState] = useState(0)
return (
<>
<Child1 update={setState} />
<Child2 state={state} />
</>
)
}
const Child1 = ({ update }) => (
<button onClick={() => update(233)}>update child2</button>
)
const Child2 = ({ state }) => <p>{state}</p>
redux
redux 与 react 没有必然关系。redux 是一个观察者模式 + compose 的实现。上述例子可以看出数据会单向传递到视图上,而数据传递需要事件来触发,即视图是数据的订阅者,数据变化,视图也相应作出变化。所以 redux 与 react 可以很好的配合。但 redux 的事件触发相对频繁,如果不做优化,react 会进行大量无用的更新(rerender)逻辑,所以在 react-redux 库中,将订阅数据的订阅器进行了优化,减少了很多 rerender。
至于需不需要引入 redux,其实仔细想,使用 context、ref 足够了。