我有一个组件,我希望能够覆盖该组件中的render
方法和某些方法。在React中,您不能使用继承。在函数式编程中可能有一种使用组合的方法,但如何将渲染和所有方法组合到单独的组件中呢?对于React默认组件函数(如componentDidUpdate
),您是否能够将其组合为一个单独的组件,并引入到更高级别的组件(HoC)中。如何在HoC的每个组成组件中传递或访问属性和状态。如果能找到一个以某种方式扩展组件并覆盖方法的示例,那就太好了。
发布于 2017-11-10 03:20:43
“使用函数式程序模拟继承--”停止,什么?你为什么要为自己选择这样的负担呢?
函数式编程并不是要翻译你在其他范例中知道的概念。在开始编写有意义的程序之前,您需要学习许多新的东西。
这里有一些来自Brian Lonsdorf's React Rally 2016 presentation的东西-它可能会向你展示彩虹末端的罐子是什么样子,但到达那里是完全靠它自己的事情。
让功能风格是新的和不同的;把旧习惯抛在门外。
const { withReducer } = Recompose
const Reducer = g =>
({
fold: g,
contramap: f =>
Reducer((state, action) => g(state, f(action))),
map: f =>
Reducer((state, action) => f(g(state, action))),
concat: o =>
Reducer((state, action) => o.fold(g(state, action), action))
})
const appReducer = Reducer((state, action) => {
switch (action.type) {
case 'set_visibility_filter':
return Object.assign({}, state, {
visibilityFilter: action.filter
})
default:
return state
}
})
const todoReducer = Reducer((state, action) => {
switch (action.type) {
case 'new_todo':
const t = { id: 0, title: action.payload.title }
return Object.assign({}, state, {
todos: state.todos.concat(t)
})
default:
return state
}
})
const Component = g =>
({
fold: g,
contramap: f =>
Component(x => g(f(x))),
concat: other =>
Component(x => <div>{g(x)} {other.fold(x)}</div>)
})
const classToFn = C =>
(props) => <C {...props} />
const Hoc = g =>
({
fold: g,
concat: other =>
Hoc(x => g(other.fold(x)))
})
// Example
// ======================
const todoApp = appReducer.concat(todoReducer)
.contramap(action => Object.assign({filter: 'all'}, action))
.map(s => Object.assign({}, s, {lastUpdated: Date()}))
const hoc = Hoc(withReducer('state', 'dispatch', todoApp.fold, {todos: []}))
const Todos = hoc.fold(({ state, dispatch }) =>
<div>
<span>Filter: {state.visibilityFilter}</span>
<ul>
{ state.todos.map((t, i) => <li key={i}>{t.title}</li>) }
</ul>
<button onClick={() =>
dispatch({ type: 'new_todo', payload: {title: 'New todo'}})}>
Add Todo
</button>
<button onClick={() =>
dispatch({ type: 'set_visibility_filter' })}>
Set Visibility
</button>
</div>
)
const TodoComp = Component(classToFn(Todos))
const Header = Component(s => <h1>Now Viewing {s}</h1>)
const ProfileLink = Component(u => <a href={`/users/${u.id}`}>{u.name}</a>)
const App = Header.contramap(s => s.pageName)
.concat(TodoComp)
.concat(ProfileLink.contramap(s => s.current_user))
.fold({ pageName: 'Home',
current_user: {id: 2, name: 'Boris' } })
ReactDOM.render(
App,
document.getElementById('container')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/recompose/0.26.0/Recompose.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
https://stackoverflow.com/questions/47202108
复制相似问题